mirror of
https://github.com/frappe/erpnext.git
synced 2026-05-01 20:48:27 +00:00
Merge branch 'develop' into feat/employee-creation-and-lifecycle
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
# Security Policy
|
||||
|
||||
The ERPNext team and community take security issues seriously. To report a security issue, fill out the form at [https://erpnext.com/security/report](https://erpnext.com/security/report).
|
||||
The ERPNext team and community take security issues seriously. To report a security issue, please go through the information mentioned [here](https://frappe.io/security).
|
||||
|
||||
You can help us make ERPNext and all it's users more secure by following the [Reporting guidelines](https://erpnext.com/security).
|
||||
You can help us make ERPNext and all its users more secure by following the [Reporting guidelines](https://frappe.io/security).
|
||||
|
||||
We appreciate your efforts to responsibly disclose your findings. We'll endeavor to respond quickly, and will keep you updated throughout the process.
|
||||
We appreciate your efforts to responsibly disclose your findings. We'll endeavor to respond quickly, and will keep you updated throughout the process.
|
||||
|
||||
@@ -69,37 +69,34 @@ class AccountingDimensionFilter(Document):
|
||||
|
||||
|
||||
def get_dimension_filter_map():
|
||||
if not frappe.flags.get("dimension_filter_map"):
|
||||
filters = frappe.db.sql(
|
||||
"""
|
||||
SELECT
|
||||
a.applicable_on_account, d.dimension_value, p.accounting_dimension,
|
||||
p.allow_or_restrict, p.fieldname, a.is_mandatory
|
||||
FROM
|
||||
`tabApplicable On Account` a,
|
||||
`tabAccounting Dimension Filter` p
|
||||
LEFT JOIN `tabAllowed Dimension` d ON d.parent = p.name
|
||||
WHERE
|
||||
p.name = a.parent
|
||||
AND p.disabled = 0
|
||||
""",
|
||||
as_dict=1,
|
||||
filters = frappe.db.sql(
|
||||
"""
|
||||
SELECT
|
||||
a.applicable_on_account, d.dimension_value, p.accounting_dimension,
|
||||
p.allow_or_restrict, p.fieldname, a.is_mandatory
|
||||
FROM
|
||||
`tabApplicable On Account` a,
|
||||
`tabAccounting Dimension Filter` p
|
||||
LEFT JOIN `tabAllowed Dimension` d ON d.parent = p.name
|
||||
WHERE
|
||||
p.name = a.parent
|
||||
AND p.disabled = 0
|
||||
""",
|
||||
as_dict=1,
|
||||
)
|
||||
|
||||
dimension_filter_map = {}
|
||||
|
||||
for f in filters:
|
||||
build_map(
|
||||
dimension_filter_map,
|
||||
f.fieldname,
|
||||
f.applicable_on_account,
|
||||
f.dimension_value,
|
||||
f.allow_or_restrict,
|
||||
f.is_mandatory,
|
||||
)
|
||||
|
||||
dimension_filter_map = {}
|
||||
|
||||
for f in filters:
|
||||
build_map(
|
||||
dimension_filter_map,
|
||||
f.fieldname,
|
||||
f.applicable_on_account,
|
||||
f.dimension_value,
|
||||
f.allow_or_restrict,
|
||||
f.is_mandatory,
|
||||
)
|
||||
frappe.flags.dimension_filter_map = dimension_filter_map
|
||||
|
||||
return frappe.flags.dimension_filter_map
|
||||
return dimension_filter_map
|
||||
|
||||
|
||||
def build_map(map_object, dimension, account, filter_value, allow_or_restrict, is_mandatory):
|
||||
|
||||
@@ -205,7 +205,7 @@
|
||||
"description": "Payment Terms from orders will be fetched into the invoices as is",
|
||||
"fieldname": "automatically_fetch_payment_terms",
|
||||
"fieldtype": "Check",
|
||||
"label": "Automatically Fetch Payment Terms from Order"
|
||||
"label": "Automatically Fetch Payment Terms from Order/Quotation"
|
||||
},
|
||||
{
|
||||
"description": "The percentage you are allowed to bill more against the amount ordered. For example, if the order value is $100 for an item and tolerance is set as 10%, then you are allowed to bill up to $110 ",
|
||||
@@ -697,7 +697,7 @@
|
||||
"index_web_pages_for_search": 1,
|
||||
"issingle": 1,
|
||||
"links": [],
|
||||
"modified": "2026-02-04 17:15:38.609327",
|
||||
"modified": "2026-02-27 01:04:09.415288",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Accounts Settings",
|
||||
|
||||
@@ -1154,7 +1154,7 @@ def get_irequests_of_payment_request(doc: str | None = None) -> list:
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_available_payment_schedules(reference_doctype, reference_name):
|
||||
def get_available_payment_schedules(reference_doctype: str, reference_name: str):
|
||||
ref_doc = frappe.get_doc(reference_doctype, reference_name)
|
||||
|
||||
if not hasattr(ref_doc, "payment_schedule") or not ref_doc.payment_schedule:
|
||||
|
||||
@@ -4,19 +4,6 @@
|
||||
frappe.ui.form.on("POS Closing Entry", {
|
||||
onload: async function (frm) {
|
||||
frm.ignore_doctypes_on_cancel_all = ["POS Invoice Merge Log", "Sales Invoice"];
|
||||
frm.set_query("pos_profile", function (doc) {
|
||||
return {
|
||||
filters: { user: doc.user },
|
||||
};
|
||||
});
|
||||
|
||||
frm.set_query("user", function (doc) {
|
||||
return {
|
||||
query: "erpnext.accounts.doctype.pos_closing_entry.pos_closing_entry.get_cashiers",
|
||||
filters: { parent: doc.pos_profile },
|
||||
};
|
||||
});
|
||||
|
||||
frm.set_query("pos_opening_entry", function (doc) {
|
||||
return { filters: { status: "Open", docstatus: 1 } };
|
||||
});
|
||||
|
||||
@@ -346,8 +346,7 @@ def apply_pricing_rule(args: str | dict, doc: str | dict | Document | None = Non
|
||||
|
||||
args = frappe._dict(args)
|
||||
|
||||
if not args.transaction_type:
|
||||
set_transaction_type(args)
|
||||
set_transaction_type(args)
|
||||
|
||||
# list of dictionaries
|
||||
out = []
|
||||
@@ -688,23 +687,23 @@ def remove_pricing_rules(item_list: str | list):
|
||||
return out
|
||||
|
||||
|
||||
def set_transaction_type(args):
|
||||
if args.transaction_type:
|
||||
def set_transaction_type(pricing_ctx: frappe._dict) -> None:
|
||||
if pricing_ctx.transaction_type in ["buying", "selling"]:
|
||||
return
|
||||
if args.doctype in ("Opportunity", "Quotation", "Sales Order", "Delivery Note", "Sales Invoice"):
|
||||
args.transaction_type = "selling"
|
||||
elif args.doctype in (
|
||||
if pricing_ctx.doctype in ("Opportunity", "Quotation", "Sales Order", "Delivery Note", "Sales Invoice"):
|
||||
pricing_ctx.transaction_type = "selling"
|
||||
elif pricing_ctx.doctype in (
|
||||
"Material Request",
|
||||
"Supplier Quotation",
|
||||
"Purchase Order",
|
||||
"Purchase Receipt",
|
||||
"Purchase Invoice",
|
||||
):
|
||||
args.transaction_type = "buying"
|
||||
elif args.customer:
|
||||
args.transaction_type = "selling"
|
||||
pricing_ctx.transaction_type = "buying"
|
||||
elif pricing_ctx.customer:
|
||||
pricing_ctx.transaction_type = "selling"
|
||||
else:
|
||||
args.transaction_type = "buying"
|
||||
pricing_ctx.transaction_type = "buying"
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
|
||||
@@ -800,8 +800,7 @@
|
||||
"hide_seconds": 1,
|
||||
"label": "Time Sheets",
|
||||
"options": "Sales Invoice Timesheet",
|
||||
"print_hide": 1,
|
||||
"read_only": 1
|
||||
"print_hide": 1
|
||||
},
|
||||
{
|
||||
"default": "0",
|
||||
@@ -2331,7 +2330,7 @@
|
||||
"link_fieldname": "consolidated_invoice"
|
||||
}
|
||||
],
|
||||
"modified": "2026-02-25 12:41:57.043459",
|
||||
"modified": "2026-02-28 17:58:56.453076",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Sales Invoice",
|
||||
|
||||
@@ -1452,6 +1452,9 @@ class SalesInvoice(SellingController):
|
||||
return asset_qty_map
|
||||
|
||||
def process_asset_depreciation(self):
|
||||
if self.is_internal_transfer():
|
||||
return
|
||||
|
||||
if (self.is_return and self.docstatus == 2) or (not self.is_return and self.docstatus == 1):
|
||||
self.depreciate_asset_on_sale()
|
||||
else:
|
||||
|
||||
@@ -8,6 +8,8 @@ import frappe
|
||||
from frappe import _
|
||||
from frappe.contacts.doctype.address.address import get_default_address
|
||||
from frappe.model.document import Document
|
||||
from frappe.query_builder import DocType
|
||||
from frappe.query_builder.functions import IfNull
|
||||
from frappe.utils import cstr
|
||||
from frappe.utils.nestedset import get_root_of
|
||||
|
||||
@@ -83,6 +85,8 @@ class TaxRule(Document):
|
||||
frappe.throw(_("Tax Template is mandatory."))
|
||||
|
||||
def validate_filters(self):
|
||||
TaxRule = DocType("Tax Rule")
|
||||
|
||||
filters = {
|
||||
"tax_type": self.tax_type,
|
||||
"customer": self.customer,
|
||||
@@ -105,33 +109,34 @@ class TaxRule(Document):
|
||||
"company": self.company,
|
||||
}
|
||||
|
||||
conds = ""
|
||||
for d in filters:
|
||||
if conds:
|
||||
conds += " and "
|
||||
conds += f"""ifnull({d}, '') = {frappe.db.escape(cstr(filters[d]))}"""
|
||||
|
||||
if self.from_date and self.to_date:
|
||||
conds += f""" and ((from_date > '{self.from_date}' and from_date < '{self.to_date}') or
|
||||
(to_date > '{self.from_date}' and to_date < '{self.to_date}') or
|
||||
('{self.from_date}' > from_date and '{self.from_date}' < to_date) or
|
||||
('{self.from_date}' = from_date and '{self.to_date}' = to_date))"""
|
||||
|
||||
elif self.from_date and not self.to_date:
|
||||
conds += f""" and to_date > '{self.from_date}'"""
|
||||
|
||||
elif self.to_date and not self.from_date:
|
||||
conds += f""" and from_date < '{self.to_date}'"""
|
||||
|
||||
tax_rule = frappe.db.sql(
|
||||
f"select name, priority \
|
||||
from `tabTax Rule` where {conds} and name != '{self.name}'",
|
||||
as_dict=1,
|
||||
query = (
|
||||
frappe.qb.from_(TaxRule).select(TaxRule.name, TaxRule.priority).where(TaxRule.name != self.name)
|
||||
)
|
||||
|
||||
if tax_rule:
|
||||
if tax_rule[0].priority == self.priority:
|
||||
frappe.throw(_("Tax Rule Conflicts with {0}").format(tax_rule[0].name), ConflictingTaxRule)
|
||||
for field, value in filters.items():
|
||||
query = query.where(IfNull(TaxRule[field], "") == cstr(value))
|
||||
|
||||
if self.from_date and self.to_date:
|
||||
query = query.where(
|
||||
((TaxRule.from_date > self.from_date) & (TaxRule.from_date < self.to_date))
|
||||
| ((TaxRule.to_date > self.from_date) & (TaxRule.to_date < self.to_date))
|
||||
| ((self.from_date > TaxRule.from_date) & (self.from_date < TaxRule.to_date))
|
||||
| ((TaxRule.from_date == self.from_date) & (TaxRule.to_date == self.to_date))
|
||||
)
|
||||
|
||||
elif self.from_date:
|
||||
query = query.where(TaxRule.to_date > self.from_date)
|
||||
|
||||
elif self.to_date:
|
||||
query = query.where(TaxRule.from_date < self.to_date)
|
||||
|
||||
tax_rule = query.run(as_dict=True)
|
||||
|
||||
if tax_rule and tax_rule[0].priority == self.priority:
|
||||
frappe.throw(
|
||||
_("Tax Rule Conflicts with {0}").format(tax_rule[0].name),
|
||||
ConflictingTaxRule,
|
||||
)
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import frappe
|
||||
from frappe.tests import IntegrationTestCase
|
||||
from frappe.utils import today
|
||||
from frappe.utils import add_days, today
|
||||
|
||||
from erpnext.accounts.doctype.purchase_invoice.test_purchase_invoice import make_purchase_invoice
|
||||
from erpnext.accounts.report.accounts_payable.accounts_payable import execute
|
||||
@@ -57,3 +57,66 @@ class TestAccountsPayable(AccountsTestMixin, IntegrationTestCase):
|
||||
if not do_not_submit:
|
||||
pi = pi.submit()
|
||||
return pi
|
||||
|
||||
def test_payment_terms_template_filters(self):
|
||||
from erpnext.controllers.accounts_controller import get_payment_terms
|
||||
|
||||
payment_term1 = frappe.get_doc(
|
||||
{"doctype": "Payment Term", "payment_term_name": "_Test 50% on 15 Days"}
|
||||
).insert()
|
||||
payment_term2 = frappe.get_doc(
|
||||
{"doctype": "Payment Term", "payment_term_name": "_Test 50% on 30 Days"}
|
||||
).insert()
|
||||
|
||||
template = frappe.get_doc(
|
||||
{
|
||||
"doctype": "Payment Terms Template",
|
||||
"template_name": "_Test 50-50",
|
||||
"terms": [
|
||||
{
|
||||
"doctype": "Payment Terms Template Detail",
|
||||
"due_date_based_on": "Day(s) after invoice date",
|
||||
"payment_term": payment_term1.name,
|
||||
"description": "_Test 50-50",
|
||||
"invoice_portion": 50,
|
||||
"credit_days": 15,
|
||||
},
|
||||
{
|
||||
"doctype": "Payment Terms Template Detail",
|
||||
"due_date_based_on": "Day(s) after invoice date",
|
||||
"payment_term": payment_term2.name,
|
||||
"description": "_Test 50-50",
|
||||
"invoice_portion": 50,
|
||||
"credit_days": 30,
|
||||
},
|
||||
],
|
||||
}
|
||||
)
|
||||
template.insert()
|
||||
|
||||
filters = {
|
||||
"company": self.company,
|
||||
"report_date": today(),
|
||||
"range": "30, 60, 90, 120",
|
||||
"based_on_payment_terms": 1,
|
||||
"payment_terms_template": template.name,
|
||||
"ageing_based_on": "Posting Date",
|
||||
}
|
||||
|
||||
pi = self.create_purchase_invoice(do_not_submit=True)
|
||||
pi.payment_terms_template = template.name
|
||||
schedule = get_payment_terms(template.name)
|
||||
pi.set("payment_schedule", [])
|
||||
|
||||
for row in schedule:
|
||||
row["due_date"] = add_days(pi.posting_date, row.get("credit_days", 0))
|
||||
pi.append("payment_schedule", row)
|
||||
|
||||
pi.save()
|
||||
pi.submit()
|
||||
|
||||
report = execute(filters)
|
||||
row = report[1][0]
|
||||
|
||||
self.assertEqual(len(report[1]), 2)
|
||||
self.assertEqual([pi.name, payment_term1.payment_term_name], [row.voucher_no, row.payment_term])
|
||||
|
||||
@@ -1035,9 +1035,8 @@ class ReceivablePayableReport:
|
||||
self,
|
||||
):
|
||||
self.customer = qb.DocType("Customer")
|
||||
|
||||
if self.filters.get("customer_group"):
|
||||
groups = get_customer_group_with_children(self.filters.customer_group)
|
||||
groups = get_party_group_with_children("Customer", self.filters.customer_group)
|
||||
customers = (
|
||||
qb.from_(self.customer)
|
||||
.select(self.customer.name)
|
||||
@@ -1049,14 +1048,18 @@ class ReceivablePayableReport:
|
||||
self.get_hierarchical_filters("Territory", "territory")
|
||||
|
||||
if self.filters.get("payment_terms_template"):
|
||||
self.qb_selection_filter.append(
|
||||
self.ple.party.isin(
|
||||
qb.from_(self.customer)
|
||||
.select(self.customer.name)
|
||||
.where(self.customer.payment_terms == self.filters.get("payment_terms_template"))
|
||||
)
|
||||
customer_ptt = self.ple.party.isin(
|
||||
qb.from_(self.customer)
|
||||
.select(self.customer.name)
|
||||
.where(self.customer.payment_terms == self.filters.get("payment_terms_template"))
|
||||
)
|
||||
|
||||
si_ptt = self.add_payment_term_template_filters("Sales Invoice")
|
||||
|
||||
sales_ptt = self.ple.against_voucher_no.isin(si_ptt)
|
||||
|
||||
self.qb_selection_filter.append(Criterion.any([customer_ptt, sales_ptt]))
|
||||
|
||||
if self.filters.get("sales_partner"):
|
||||
self.qb_selection_filter.append(
|
||||
self.ple.party.isin(
|
||||
@@ -1081,14 +1084,53 @@ class ReceivablePayableReport:
|
||||
)
|
||||
|
||||
if self.filters.get("payment_terms_template"):
|
||||
self.qb_selection_filter.append(
|
||||
self.ple.party.isin(
|
||||
qb.from_(supplier)
|
||||
.select(supplier.name)
|
||||
.where(supplier.payment_terms == self.filters.get("supplier_group"))
|
||||
)
|
||||
supplier_ptt = self.ple.party.isin(
|
||||
qb.from_(supplier)
|
||||
.select(supplier.name)
|
||||
.where(supplier.payment_terms == self.filters.get("payment_terms_template"))
|
||||
)
|
||||
|
||||
pi_ptt = self.add_payment_term_template_filters("Purchase Invoice")
|
||||
|
||||
purchase_ptt = self.ple.against_voucher_no.isin(pi_ptt)
|
||||
|
||||
self.qb_selection_filter.append(Criterion.any([supplier_ptt, purchase_ptt]))
|
||||
|
||||
def add_payment_term_template_filters(self, dtype):
|
||||
voucher_type = qb.DocType(dtype)
|
||||
|
||||
ptt = (
|
||||
qb.from_(voucher_type)
|
||||
.select(voucher_type.name)
|
||||
.where(voucher_type.payment_terms_template == self.filters.get("payment_terms_template"))
|
||||
.where(voucher_type.company == self.filters.company)
|
||||
)
|
||||
|
||||
if dtype == "Purchase Invoice":
|
||||
party = "Supplier"
|
||||
party_group_type = "supplier_group"
|
||||
acc_type = "credit_to"
|
||||
else:
|
||||
party = "Customer"
|
||||
party_group_type = "customer_group"
|
||||
acc_type = "debit_to"
|
||||
|
||||
if self.filters.get(party_group_type):
|
||||
party_groups = get_party_group_with_children(party, self.filters.get(party_group_type))
|
||||
ptt = ptt.where((voucher_type[party_group_type]).isin(party_groups))
|
||||
|
||||
if self.filters.party:
|
||||
ptt = ptt.where((voucher_type[party.lower()]).isin(self.filters.party))
|
||||
|
||||
if self.filters.cost_center:
|
||||
cost_centers = get_cost_centers_with_children(self.filters.cost_center)
|
||||
ptt = ptt.where(voucher_type.cost_center.isin(cost_centers))
|
||||
|
||||
if self.filters.party_account:
|
||||
ptt = ptt.where(voucher_type[acc_type] == self.filters.party_account)
|
||||
|
||||
return ptt
|
||||
|
||||
def get_hierarchical_filters(self, doctype, key):
|
||||
lft, rgt = frappe.db.get_value(doctype, self.filters.get(key), ["lft", "rgt"])
|
||||
|
||||
@@ -1330,20 +1372,26 @@ class ReceivablePayableReport:
|
||||
self.err_journals = [x[0] for x in results] if results else []
|
||||
|
||||
|
||||
def get_customer_group_with_children(customer_groups):
|
||||
if not isinstance(customer_groups, list):
|
||||
customer_groups = [d.strip() for d in customer_groups.strip().split(",") if d]
|
||||
def get_party_group_with_children(party, party_groups):
|
||||
if party not in ("Customer", "Supplier"):
|
||||
return []
|
||||
|
||||
all_customer_groups = []
|
||||
for d in customer_groups:
|
||||
if frappe.db.exists("Customer Group", d):
|
||||
lft, rgt = frappe.db.get_value("Customer Group", d, ["lft", "rgt"])
|
||||
children = frappe.get_all("Customer Group", filters={"lft": [">=", lft], "rgt": ["<=", rgt]})
|
||||
all_customer_groups += [c.name for c in children]
|
||||
group_dtype = f"{party} Group"
|
||||
if not isinstance(party_groups, list):
|
||||
party_groups = [d.strip() for d in party_groups.strip().split(",") if d]
|
||||
|
||||
all_party_groups = []
|
||||
for d in party_groups:
|
||||
if frappe.db.exists(group_dtype, d):
|
||||
lft, rgt = frappe.db.get_value(group_dtype, d, ["lft", "rgt"])
|
||||
children = frappe.get_all(
|
||||
group_dtype, filters={"lft": [">=", lft], "rgt": ["<=", rgt]}, pluck="name"
|
||||
)
|
||||
all_party_groups += children
|
||||
else:
|
||||
frappe.throw(_("Customer Group: {0} does not exist").format(d))
|
||||
frappe.throw(_("{0}: {1} does not exist").format(group_dtype, d))
|
||||
|
||||
return list(set(all_customer_groups))
|
||||
return list(set(all_party_groups))
|
||||
|
||||
|
||||
class InitSQLProceduresForAR:
|
||||
|
||||
@@ -1139,3 +1139,66 @@ class TestAccountsReceivable(AccountsTestMixin, IntegrationTestCase):
|
||||
self.assertEqual(len(report[1]), 1)
|
||||
row = report[1][0]
|
||||
self.assertEqual(expected_data_after_payment, [row.voucher_no, row.cost_center, row.outstanding])
|
||||
|
||||
def test_payment_terms_template_filters(self):
|
||||
from erpnext.controllers.accounts_controller import get_payment_terms
|
||||
|
||||
payment_term1 = frappe.get_doc(
|
||||
{"doctype": "Payment Term", "payment_term_name": "_Test 50% on 15 Days"}
|
||||
).insert()
|
||||
payment_term2 = frappe.get_doc(
|
||||
{"doctype": "Payment Term", "payment_term_name": "_Test 50% on 30 Days"}
|
||||
).insert()
|
||||
|
||||
template = frappe.get_doc(
|
||||
{
|
||||
"doctype": "Payment Terms Template",
|
||||
"template_name": "_Test 50-50",
|
||||
"terms": [
|
||||
{
|
||||
"doctype": "Payment Terms Template Detail",
|
||||
"due_date_based_on": "Day(s) after invoice date",
|
||||
"payment_term": payment_term1.name,
|
||||
"description": "_Test 50-50",
|
||||
"invoice_portion": 50,
|
||||
"credit_days": 15,
|
||||
},
|
||||
{
|
||||
"doctype": "Payment Terms Template Detail",
|
||||
"due_date_based_on": "Day(s) after invoice date",
|
||||
"payment_term": payment_term2.name,
|
||||
"description": "_Test 50-50",
|
||||
"invoice_portion": 50,
|
||||
"credit_days": 30,
|
||||
},
|
||||
],
|
||||
}
|
||||
)
|
||||
template.insert()
|
||||
|
||||
filters = {
|
||||
"company": self.company,
|
||||
"report_date": today(),
|
||||
"range": "30, 60, 90, 120",
|
||||
"based_on_payment_terms": 1,
|
||||
"payment_terms_template": template.name,
|
||||
"ageing_based_on": "Posting Date",
|
||||
}
|
||||
|
||||
si = self.create_sales_invoice(no_payment_schedule=True, do_not_submit=True)
|
||||
si.payment_terms_template = template.name
|
||||
schedule = get_payment_terms(template.name)
|
||||
si.set("payment_schedule", [])
|
||||
|
||||
for row in schedule:
|
||||
row["due_date"] = add_days(si.posting_date, row.get("credit_days", 0))
|
||||
si.append("payment_schedule", row)
|
||||
|
||||
si.save()
|
||||
si.submit()
|
||||
|
||||
report = execute(filters)
|
||||
row = report[1][0]
|
||||
|
||||
self.assertEqual(len(report[1]), 2)
|
||||
self.assertEqual([si.name, payment_term1.payment_term_name], [row.voucher_no, row.payment_term])
|
||||
|
||||
@@ -5,6 +5,7 @@ import frappe
|
||||
from frappe import _
|
||||
from frappe.utils import add_months, flt, formatdate
|
||||
|
||||
from erpnext.accounts.doctype.accounting_dimension.accounting_dimension import get_dimensions
|
||||
from erpnext.accounts.utils import get_fiscal_year
|
||||
from erpnext.controllers.trends import get_period_date_ranges
|
||||
|
||||
@@ -13,6 +14,8 @@ def execute(filters=None):
|
||||
if not filters:
|
||||
filters = {}
|
||||
|
||||
validate_filters(filters)
|
||||
|
||||
columns = get_columns(filters)
|
||||
if filters.get("budget_against_filter"):
|
||||
dimensions = filters.get("budget_against_filter")
|
||||
@@ -31,6 +34,10 @@ def execute(filters=None):
|
||||
return columns, data, None, chart_data
|
||||
|
||||
|
||||
def validate_filters(filters):
|
||||
validate_budget_dimensions(filters)
|
||||
|
||||
|
||||
def get_budget_records(filters, dimensions):
|
||||
budget_against_field = frappe.scrub(filters["budget_against"])
|
||||
|
||||
@@ -51,7 +58,7 @@ def get_budget_records(filters, dimensions):
|
||||
b.company = %s
|
||||
AND b.docstatus = 1
|
||||
AND b.budget_against = %s
|
||||
AND b.{budget_against_field} IN ({', '.join(['%s'] * len(dimensions))})
|
||||
AND b.{budget_against_field} IN ({", ".join(["%s"] * len(dimensions))})
|
||||
AND (
|
||||
b.from_fiscal_year <= %s
|
||||
AND b.to_fiscal_year >= %s
|
||||
@@ -404,6 +411,17 @@ def get_budget_dimensions(filters):
|
||||
) # nosec
|
||||
|
||||
|
||||
def validate_budget_dimensions(filters):
|
||||
dimensions = [d.get("document_type") for d in get_dimensions(with_cost_center_and_project=True)[0]]
|
||||
if filters.get("budget_against") and filters.get("budget_against") not in dimensions:
|
||||
frappe.throw(
|
||||
title=_("Invalid Accounting Dimension"),
|
||||
msg=_("{0} is not a valid Accounting Dimension.").format(
|
||||
frappe.bold(filters.get("budget_against"))
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
def build_comparison_chart_data(filters, columns, data):
|
||||
if not data:
|
||||
return None
|
||||
|
||||
@@ -656,7 +656,11 @@ def set_gl_entries_by_account(
|
||||
query = query.where(Criterion.all(additional_conditions))
|
||||
gl_entries = query.run(as_dict=True)
|
||||
|
||||
if filters and filters.get("presentation_currency") != d.default_currency:
|
||||
if (
|
||||
filters
|
||||
and filters.get("presentation_currency")
|
||||
and filters.get("presentation_currency") != d.default_currency
|
||||
):
|
||||
currency_info["company"] = d.name
|
||||
currency_info["company_currency"] = d.default_currency
|
||||
convert_to_presentation_currency(gl_entries, currency_info)
|
||||
|
||||
@@ -37,6 +37,20 @@ function get_filters() {
|
||||
});
|
||||
},
|
||||
},
|
||||
{
|
||||
fieldname: "party_type",
|
||||
label: __("Party Type"),
|
||||
fieldtype: "Link",
|
||||
options: "Party Type",
|
||||
width: 100,
|
||||
},
|
||||
{
|
||||
fieldname: "party",
|
||||
label: __("Party"),
|
||||
fieldtype: "Dynamic Link",
|
||||
options: "party_type",
|
||||
width: 100,
|
||||
},
|
||||
{
|
||||
fieldname: "voucher_no",
|
||||
label: __("Voucher No"),
|
||||
|
||||
@@ -68,6 +68,12 @@ class General_Payment_Ledger_Comparison:
|
||||
if self.filters.period_end_date:
|
||||
filter_criterion.append(gle.posting_date.lte(self.filters.period_end_date))
|
||||
|
||||
if self.filters.party_type:
|
||||
filter_criterion.append(gle.party_type.eq(self.filters.party_type))
|
||||
|
||||
if self.filters.party:
|
||||
filter_criterion.append(gle.party.eq(self.filters.party))
|
||||
|
||||
if acc_type == "receivable":
|
||||
outstanding = (Sum(gle.debit) - Sum(gle.credit)).as_("outstanding")
|
||||
else:
|
||||
@@ -111,6 +117,12 @@ class General_Payment_Ledger_Comparison:
|
||||
if self.filters.period_end_date:
|
||||
filter_criterion.append(ple.posting_date.lte(self.filters.period_end_date))
|
||||
|
||||
if self.filters.party_type:
|
||||
filter_criterion.append(ple.party_type.eq(self.filters.party_type))
|
||||
|
||||
if self.filters.party:
|
||||
filter_criterion.append(ple.party.eq(self.filters.party))
|
||||
|
||||
self.account_types[acc_type].ple = (
|
||||
qb.from_(ple)
|
||||
.select(
|
||||
|
||||
@@ -7,6 +7,7 @@ import math
|
||||
|
||||
import frappe
|
||||
from frappe import _
|
||||
from frappe.model.document import Document
|
||||
from frappe.query_builder.functions import IfNull, Sum
|
||||
from frappe.utils import (
|
||||
cint,
|
||||
@@ -986,7 +987,7 @@ class Asset(AccountsController):
|
||||
return False
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_depreciation_rate(self, args, on_validate=False):
|
||||
def get_depreciation_rate(self, args: str | dict | Document, on_validate: bool = False):
|
||||
if isinstance(args, str):
|
||||
args = json.loads(args)
|
||||
|
||||
|
||||
@@ -16,6 +16,7 @@ erpnext.assets.AssetCapitalization = class AssetCapitalization extends erpnext.s
|
||||
|
||||
refresh() {
|
||||
this.show_general_ledger();
|
||||
erpnext.toggle_serial_batch_fields(this.frm);
|
||||
|
||||
if (this.frm.doc.stock_items && this.frm.doc.stock_items.length) {
|
||||
this.show_stock_ledger();
|
||||
|
||||
@@ -90,7 +90,7 @@ def update_asset_maintenance_log_status():
|
||||
|
||||
@frappe.whitelist()
|
||||
@frappe.validate_and_sanitize_search_inputs
|
||||
def get_maintenance_tasks(doctype, txt, searchfield, start, page_len, filters):
|
||||
def get_maintenance_tasks(doctype: str, txt: str, searchfield: str, start: int, page_len: int, filters: dict):
|
||||
asset_maintenance_tasks = frappe.db.get_values(
|
||||
"Asset Maintenance Task", {"parent": filters.get("asset_maintenance")}, "maintenance_task"
|
||||
)
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
"order_confirmation_date",
|
||||
"column_break_7",
|
||||
"transaction_date",
|
||||
"transaction_time",
|
||||
"schedule_date",
|
||||
"column_break1",
|
||||
"is_subcontracted",
|
||||
@@ -1311,6 +1312,14 @@
|
||||
{
|
||||
"fieldname": "section_break_tnkm",
|
||||
"fieldtype": "Section Break"
|
||||
},
|
||||
{
|
||||
"default": "Now",
|
||||
"depends_on": "is_internal_supplier",
|
||||
"fieldname": "transaction_time",
|
||||
"fieldtype": "Time",
|
||||
"label": "Time",
|
||||
"mandatory_depends_on": "is_internal_supplier"
|
||||
}
|
||||
],
|
||||
"grid_page_length": 50,
|
||||
@@ -1318,7 +1327,7 @@
|
||||
"idx": 105,
|
||||
"is_submittable": 1,
|
||||
"links": [],
|
||||
"modified": "2026-02-23 13:22:33.323946",
|
||||
"modified": "2026-03-02 00:40:47.119584",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Buying",
|
||||
"name": "Purchase Order",
|
||||
|
||||
@@ -167,6 +167,7 @@ class PurchaseOrder(BuyingController):
|
||||
total_qty: DF.Float
|
||||
total_taxes_and_charges: DF.Currency
|
||||
transaction_date: DF.Date
|
||||
transaction_time: DF.Time | None
|
||||
# end: auto-generated types
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
|
||||
@@ -250,10 +250,17 @@ frappe.ui.form.on("Request for Quotation", {
|
||||
"subject",
|
||||
])
|
||||
.then((r) => {
|
||||
frm.set_value(
|
||||
"message_for_supplier",
|
||||
r.message.use_html ? r.message.response_html : r.message.response
|
||||
);
|
||||
if (r.message.use_html) {
|
||||
frm.set_value({
|
||||
mfs_html: r.message.response_html,
|
||||
use_html: 1,
|
||||
});
|
||||
} else {
|
||||
frm.set_value({
|
||||
message_for_supplier: r.message.response,
|
||||
use_html: 0,
|
||||
});
|
||||
}
|
||||
frm.set_value("subject", r.message.subject);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -31,7 +31,9 @@
|
||||
"send_document_print",
|
||||
"sec_break_email_2",
|
||||
"subject",
|
||||
"use_html",
|
||||
"message_for_supplier",
|
||||
"mfs_html",
|
||||
"terms_section_break",
|
||||
"incoterm",
|
||||
"named_place",
|
||||
@@ -142,12 +144,13 @@
|
||||
{
|
||||
"allow_on_submit": 1,
|
||||
"default": "Please supply the specified items at the best possible rates",
|
||||
"depends_on": "eval:doc.use_html == 0",
|
||||
"fieldname": "message_for_supplier",
|
||||
"fieldtype": "Text Editor",
|
||||
"in_list_view": 1,
|
||||
"label": "Message for Supplier",
|
||||
"print_hide": 1,
|
||||
"reqd": 1
|
||||
"mandatory_depends_on": "eval:doc.use_html == 0",
|
||||
"print_hide": 1
|
||||
},
|
||||
{
|
||||
"collapsible": 1,
|
||||
@@ -324,6 +327,22 @@
|
||||
"label": "Subject",
|
||||
"not_nullable": 1,
|
||||
"reqd": 1
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 1,
|
||||
"depends_on": "eval:doc.use_html == 1",
|
||||
"fieldname": "mfs_html",
|
||||
"fieldtype": "Code",
|
||||
"label": "Message for Supplier",
|
||||
"mandatory_depends_on": "eval:doc.use_html == 1",
|
||||
"print_hide": 1
|
||||
},
|
||||
{
|
||||
"default": "0",
|
||||
"fieldname": "use_html",
|
||||
"fieldtype": "Check",
|
||||
"hidden": 1,
|
||||
"label": "Use HTML"
|
||||
}
|
||||
],
|
||||
"grid_page_length": 50,
|
||||
@@ -331,7 +350,7 @@
|
||||
"index_web_pages_for_search": 1,
|
||||
"is_submittable": 1,
|
||||
"links": [],
|
||||
"modified": "2026-01-06 10:31:08.747043",
|
||||
"modified": "2026-03-01 23:38:48.079274",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Buying",
|
||||
"name": "Request for Quotation",
|
||||
|
||||
@@ -48,7 +48,8 @@ class RequestforQuotation(BuyingController):
|
||||
incoterm: DF.Link | None
|
||||
items: DF.Table[RequestforQuotationItem]
|
||||
letter_head: DF.Link | None
|
||||
message_for_supplier: DF.TextEditor
|
||||
message_for_supplier: DF.TextEditor | None
|
||||
mfs_html: DF.Code | None
|
||||
named_place: DF.Data | None
|
||||
naming_series: DF.Literal["PUR-RFQ-.YYYY.-"]
|
||||
opportunity: DF.Link | None
|
||||
@@ -62,6 +63,7 @@ class RequestforQuotation(BuyingController):
|
||||
tc_name: DF.Link | None
|
||||
terms: DF.TextEditor | None
|
||||
transaction_date: DF.Date
|
||||
use_html: DF.Check
|
||||
vendor: DF.Link | None
|
||||
# end: auto-generated types
|
||||
|
||||
@@ -101,8 +103,16 @@ class RequestforQuotation(BuyingController):
|
||||
["use_html", "response", "response_html", "subject"],
|
||||
as_dict=True,
|
||||
)
|
||||
if not self.message_for_supplier:
|
||||
self.message_for_supplier = data.response_html if data.use_html else data.response
|
||||
|
||||
self.use_html = data.use_html
|
||||
|
||||
if data.use_html:
|
||||
if not self.mfs_html:
|
||||
self.mfs_html = data.response_html
|
||||
else:
|
||||
if not self.message_for_supplier:
|
||||
self.message_for_supplier = data.response
|
||||
|
||||
if not self.subject:
|
||||
self.subject = data.subject
|
||||
|
||||
@@ -305,7 +315,10 @@ class RequestforQuotation(BuyingController):
|
||||
else:
|
||||
sender = frappe.session.user not in STANDARD_USERS and frappe.session.user or None
|
||||
|
||||
rendered_message = frappe.render_template(self.message_for_supplier, doc_args)
|
||||
message_template = self.mfs_html if self.use_html else self.message_for_supplier
|
||||
# nosemgrep: frappe-semgrep-rules.rules.security.frappe-ssti
|
||||
rendered_message = frappe.render_template(message_template, doc_args)
|
||||
|
||||
subject_source = (
|
||||
self.subject
|
||||
or frappe.get_value("Email Template", self.email_template, "subject")
|
||||
|
||||
@@ -34,7 +34,7 @@ class TestPurchaseOrder(IntegrationTestCase):
|
||||
self.assertEqual(sq.get("items")[1].rate, 300)
|
||||
self.assertEqual(sq.get("items")[1].description, "test")
|
||||
|
||||
def test_update_supplier_quotation_child_rate_disallow(self):
|
||||
def test_update_supplier_quotation_child_rate(self):
|
||||
sq = frappe.copy_doc(self.globalTestRecords["Supplier Quotation"][0])
|
||||
sq.submit()
|
||||
trans_item = json.dumps(
|
||||
@@ -47,6 +47,22 @@ class TestPurchaseOrder(IntegrationTestCase):
|
||||
},
|
||||
]
|
||||
)
|
||||
update_child_qty_rate("Supplier Quotation", trans_item, sq.name)
|
||||
sq.reload()
|
||||
self.assertEqual(sq.get("items")[0].rate, 300)
|
||||
po = make_purchase_order(sq.name)
|
||||
po.schedule_date = add_days(today(), 1)
|
||||
po.submit()
|
||||
trans_item = json.dumps(
|
||||
[
|
||||
{
|
||||
"item_code": sq.items[0].item_code,
|
||||
"rate": 20,
|
||||
"qty": sq.items[0].qty,
|
||||
"docname": sq.items[0].name,
|
||||
},
|
||||
]
|
||||
)
|
||||
self.assertRaises(
|
||||
frappe.ValidationError, update_child_qty_rate, "Supplier Quotation", trans_item, sq.name
|
||||
)
|
||||
|
||||
@@ -165,7 +165,7 @@ def get_data(filters):
|
||||
"cost_center": po.cost_center,
|
||||
"project": po.project,
|
||||
"requesting_site": po.warehouse,
|
||||
"requestor": po.owner,
|
||||
"requestor": mr_record.get("owner", po.owner),
|
||||
"material_request_no": po.material_request,
|
||||
"item_code": po.item_code,
|
||||
"quantity": flt(po.qty),
|
||||
|
||||
@@ -2526,13 +2526,14 @@ class AccountsController(TransactionBase):
|
||||
grand_total = flt(self.get("rounded_total") or self.grand_total)
|
||||
automatically_fetch_payment_terms = 0
|
||||
|
||||
if self.doctype in ("Sales Invoice", "Purchase Invoice"):
|
||||
base_grand_total = base_grand_total - flt(self.base_write_off_amount)
|
||||
grand_total = grand_total - flt(self.write_off_amount)
|
||||
if self.doctype in ("Sales Invoice", "Purchase Invoice", "Sales Order"):
|
||||
po_or_so, doctype, fieldname = self.get_order_details()
|
||||
automatically_fetch_payment_terms = cint(
|
||||
frappe.get_single_value("Accounts Settings", "automatically_fetch_payment_terms")
|
||||
)
|
||||
if self.doctype != "Sales Order":
|
||||
base_grand_total = base_grand_total - flt(self.base_write_off_amount)
|
||||
grand_total = grand_total - flt(self.write_off_amount)
|
||||
|
||||
if self.get("total_advance"):
|
||||
if party_account_currency == self.company_currency:
|
||||
@@ -2548,7 +2549,7 @@ class AccountsController(TransactionBase):
|
||||
|
||||
if not self.get("payment_schedule"):
|
||||
if (
|
||||
self.doctype in ["Sales Invoice", "Purchase Invoice"]
|
||||
self.doctype in ["Sales Invoice", "Purchase Invoice", "Sales Order"]
|
||||
and automatically_fetch_payment_terms
|
||||
and self.linked_order_has_payment_terms(po_or_so, fieldname, doctype)
|
||||
):
|
||||
@@ -2606,16 +2607,18 @@ class AccountsController(TransactionBase):
|
||||
if not self.get("items"):
|
||||
return None, None, None
|
||||
if self.doctype == "Sales Invoice":
|
||||
po_or_so = self.get("items")[0].get("sales_order")
|
||||
po_or_so_doctype = "Sales Order"
|
||||
po_or_so_doctype_name = "sales_order"
|
||||
|
||||
prev_doc = self.get("items")[0].get("sales_order")
|
||||
prev_doctype = "Sales Order"
|
||||
prev_doctype_name = "sales_order"
|
||||
elif self.doctype == "Purchase Invoice":
|
||||
prev_doc = self.get("items")[0].get("purchase_order")
|
||||
prev_doctype = "Purchase Order"
|
||||
prev_doctype_name = "purchase_order"
|
||||
else:
|
||||
po_or_so = self.get("items")[0].get("purchase_order")
|
||||
po_or_so_doctype = "Purchase Order"
|
||||
po_or_so_doctype_name = "purchase_order"
|
||||
|
||||
return po_or_so, po_or_so_doctype, po_or_so_doctype_name
|
||||
prev_doc = self.get("items")[0].get("prevdoc_docname")
|
||||
prev_doctype = "Quotation"
|
||||
prev_doctype_name = "prevdoc_docname"
|
||||
return prev_doc, prev_doctype, prev_doctype_name
|
||||
|
||||
def linked_order_has_payment_terms(self, po_or_so, fieldname, doctype):
|
||||
if po_or_so and self.all_items_have_same_po_or_so(po_or_so, fieldname):
|
||||
@@ -3886,20 +3889,28 @@ def update_child_qty_rate(
|
||||
return frappe.db.get_single_value("Buying Settings", "allow_zero_qty_in_purchase_order") or False
|
||||
return False
|
||||
|
||||
def validate_quantity(child_item, new_data):
|
||||
def validate_quantity_and_rate(child_item, new_data):
|
||||
if not flt(new_data.get("qty")) and not is_allowed_zero_qty():
|
||||
frappe.throw(
|
||||
_("Row #{0}: Quantity for Item {1} cannot be zero.").format(
|
||||
_("Row #{0}:Quantity for Item {1} cannot be zero.").format(
|
||||
new_data.get("idx"), frappe.bold(new_data.get("item_code"))
|
||||
),
|
||||
title=_("Invalid Qty"),
|
||||
)
|
||||
|
||||
if parent_doctype == "Sales Order" and flt(new_data.get("qty")) < flt(child_item.delivered_qty):
|
||||
frappe.throw(_("Cannot set quantity less than delivered quantity"))
|
||||
qty_limits = {
|
||||
"Sales Order": ("delivered_qty", _("Cannot set quantity less than delivered quantity")),
|
||||
"Purchase Order": ("received_qty", _("Cannot set quantity less than received quantity")),
|
||||
}
|
||||
|
||||
if parent_doctype == "Purchase Order" and flt(new_data.get("qty")) < flt(child_item.received_qty):
|
||||
frappe.throw(_("Cannot set quantity less than received quantity"))
|
||||
if parent_doctype in qty_limits:
|
||||
qty_field, error_message = qty_limits[parent_doctype]
|
||||
if flt(new_data.get("qty")) < flt(child_item.get(qty_field)):
|
||||
frappe.throw(
|
||||
_("Row #{0}:").format(new_data.get("idx"))
|
||||
+ error_message.format(frappe.bold(new_data.get("item_code"))),
|
||||
title=_("Invalid Qty"),
|
||||
)
|
||||
|
||||
if parent_doctype in ["Quotation", "Supplier Quotation"]:
|
||||
if (parent_doctype == "Quotation" and not ordered_items) or (
|
||||
@@ -3912,7 +3923,15 @@ def update_child_qty_rate(
|
||||
if parent_doctype == "Quotation"
|
||||
else purchased_items.get(child_item.name)
|
||||
)
|
||||
|
||||
if qty_to_check:
|
||||
if not rate_unchanged:
|
||||
frappe.throw(
|
||||
_(
|
||||
"Cannot update rate as item {0} is already ordered or purchased against this quotation"
|
||||
).format(frappe.bold(new_data.get("item_code")))
|
||||
)
|
||||
|
||||
if flt(new_data.get("qty")) < qty_to_check:
|
||||
frappe.throw(_("Cannot reduce quantity than ordered or purchased quantity"))
|
||||
|
||||
@@ -4031,10 +4050,7 @@ def update_child_qty_rate(
|
||||
):
|
||||
continue
|
||||
|
||||
validate_quantity(child_item, d)
|
||||
if parent_doctype in ["Quotation", "Supplier Quotation"]:
|
||||
if not rate_unchanged:
|
||||
frappe.throw(_("Rates cannot be modified for quoted items"))
|
||||
validate_quantity_and_rate(child_item, d)
|
||||
|
||||
if flt(child_item.get("qty")) != flt(d.get("qty")):
|
||||
any_qty_changed = True
|
||||
|
||||
@@ -1012,7 +1012,14 @@ def get_serial_batches_based_on_bundle(doctype, field, _bundle_ids):
|
||||
|
||||
if doctype == "Packed Item":
|
||||
if key is None:
|
||||
key = frappe.get_cached_value("Packed Item", row.voucher_detail_no, field)
|
||||
key = frappe.get_cached_value(
|
||||
"Packed Item",
|
||||
{"parent_detail_docname": row.voucher_detail_no, "item_code": row.item_code},
|
||||
field,
|
||||
)
|
||||
if key is None:
|
||||
key = frappe.get_cached_value("Packed Item", row.voucher_detail_no, field)
|
||||
|
||||
if row.voucher_type == "Delivery Note":
|
||||
key = frappe.get_cached_value("Delivery Note Item", key, "dn_detail")
|
||||
elif row.voucher_type == "Sales Invoice":
|
||||
|
||||
@@ -333,9 +333,10 @@ class SellingController(StockController):
|
||||
if is_internal_customer or not is_stock_item:
|
||||
continue
|
||||
|
||||
if item.get("incoming_rate") and item.base_net_rate < (
|
||||
rate_field = "valuation_rate" if self.doctype in ["Sales Order", "Quotation"] else "incoming_rate"
|
||||
if item.get(rate_field) and item.base_net_rate < (
|
||||
valuation_rate := flt(
|
||||
item.incoming_rate * (item.conversion_factor or 1), item.precision("base_net_rate")
|
||||
item.get(rate_field) * (item.conversion_factor or 1), item.precision("base_net_rate")
|
||||
)
|
||||
):
|
||||
throw_message(
|
||||
|
||||
@@ -63,6 +63,8 @@ class StockController(AccountsController):
|
||||
|
||||
if not self.get("is_return"):
|
||||
self.validate_inspection()
|
||||
|
||||
self.validate_warehouse_of_sabb()
|
||||
self.validate_serialized_batch()
|
||||
self.clean_serial_nos()
|
||||
self.validate_customer_provided_item()
|
||||
@@ -75,6 +77,45 @@ class StockController(AccountsController):
|
||||
super().on_update()
|
||||
self.check_zero_rate()
|
||||
|
||||
def validate_warehouse_of_sabb(self):
|
||||
if self.is_internal_transfer():
|
||||
return
|
||||
|
||||
doc_before_save = self.get_doc_before_save()
|
||||
|
||||
for row in self.items:
|
||||
if not row.get("serial_and_batch_bundle"):
|
||||
continue
|
||||
|
||||
sabb_details = frappe.db.get_value(
|
||||
"Serial and Batch Bundle",
|
||||
row.serial_and_batch_bundle,
|
||||
["type_of_transaction", "warehouse", "has_serial_no"],
|
||||
as_dict=True,
|
||||
)
|
||||
if not sabb_details:
|
||||
continue
|
||||
|
||||
if sabb_details.type_of_transaction != "Outward":
|
||||
continue
|
||||
|
||||
warehouse = row.get("warehouse") or row.get("s_warehouse")
|
||||
if sabb_details.warehouse != warehouse:
|
||||
frappe.throw(
|
||||
_(
|
||||
"Row #{0}: Warehouse {1} does not match with the warehouse {2} in Serial and Batch Bundle {3}."
|
||||
).format(row.idx, warehouse, sabb_details.warehouse, row.serial_and_batch_bundle)
|
||||
)
|
||||
|
||||
if self.doctype == "Stock Reconciliation":
|
||||
continue
|
||||
|
||||
if sabb_details.has_serial_no and doc_before_save and doc_before_save.get("items"):
|
||||
prev_row = doc_before_save.get("items", {"idx": row.idx})
|
||||
if prev_row and prev_row[0].serial_and_batch_bundle != row.serial_and_batch_bundle:
|
||||
sabb_doc = frappe.get_doc("Serial and Batch Bundle", row.serial_and_batch_bundle)
|
||||
sabb_doc.validate_serial_no_status()
|
||||
|
||||
def reset_conversion_factor(self):
|
||||
for row in self.get("items"):
|
||||
if row.uom != row.stock_uom:
|
||||
@@ -2087,7 +2128,9 @@ def check_item_quality_inspection(doctype: str, items: str | list[dict]):
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
def make_quality_inspections(doctype: str, docname: str, items: str | list, inspection_type: str):
|
||||
def make_quality_inspections(
|
||||
company: str, doctype: str, docname: str, items: str | list, inspection_type: str
|
||||
):
|
||||
if isinstance(items, str):
|
||||
items = json.loads(items)
|
||||
|
||||
@@ -2106,6 +2149,7 @@ def make_quality_inspections(doctype: str, docname: str, items: str | list, insp
|
||||
|
||||
quality_inspection = frappe.get_doc(
|
||||
{
|
||||
"company": company,
|
||||
"doctype": "Quality Inspection",
|
||||
"inspection_type": inspection_type,
|
||||
"inspected_by": frappe.session.user,
|
||||
|
||||
@@ -49,6 +49,7 @@ class TestReactivity(AccountsTestMixin, IntegrationTestCase):
|
||||
"debit_to": self.debit_to,
|
||||
"posting_date": today(),
|
||||
"cost_center": self.cost_center,
|
||||
"currency": "INR",
|
||||
"conversion_rate": 1,
|
||||
"selling_price_list": self.price_list,
|
||||
}
|
||||
|
||||
@@ -34,7 +34,7 @@ class ContractTemplate(Document):
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_contract_template(template_name, doc):
|
||||
def get_contract_template(template_name: str, doc: str | dict | Document):
|
||||
if isinstance(doc, str):
|
||||
doc = json.loads(doc)
|
||||
|
||||
|
||||
@@ -10,8 +10,10 @@ from frappe.contacts.address_and_contact import (
|
||||
from frappe.contacts.doctype.address.address import get_default_address
|
||||
from frappe.contacts.doctype.contact.contact import get_default_contact
|
||||
from frappe.email.inbox import link_communication_to_document
|
||||
from frappe.model.document import Document
|
||||
from frappe.model.mapper import get_mapped_doc
|
||||
from frappe.utils import comma_and, get_link_to_form, has_gravatar, validate_email_address
|
||||
from frappe.utils.data import DateTimeLikeObject
|
||||
|
||||
from erpnext.accounts.party import set_taxes
|
||||
from erpnext.controllers.selling_controller import SellingController
|
||||
@@ -240,7 +242,7 @@ class Lead(SellingController, CRMNote):
|
||||
return frappe.db.get_value("Quotation", {"party_name": self.name, "docstatus": 1, "status": "Lost"})
|
||||
|
||||
@frappe.whitelist()
|
||||
def create_prospect_and_contact(self, data):
|
||||
def create_prospect_and_contact(self, data: dict):
|
||||
data = frappe._dict(data)
|
||||
if data.create_contact:
|
||||
self.create_contact()
|
||||
@@ -314,7 +316,7 @@ class Lead(SellingController, CRMNote):
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
def make_customer(source_name, target_doc=None):
|
||||
def make_customer(source_name: str, target_doc: str | Document | None = None):
|
||||
return _make_customer(source_name, target_doc)
|
||||
|
||||
|
||||
@@ -361,7 +363,7 @@ def _make_customer(source_name, target_doc=None, ignore_permissions=False):
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
def make_opportunity(source_name, target_doc=None):
|
||||
def make_opportunity(source_name: str, target_doc: str | Document | None = None):
|
||||
def set_missing_values(source, target):
|
||||
_set_missing_values(source, target)
|
||||
|
||||
@@ -391,7 +393,7 @@ def make_opportunity(source_name, target_doc=None):
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
def make_quotation(source_name, target_doc=None):
|
||||
def make_quotation(source_name: str, target_doc: str | Document | None = None):
|
||||
def set_missing_values(source, target):
|
||||
_set_missing_values(source, target)
|
||||
|
||||
@@ -442,7 +444,12 @@ def _set_missing_values(source, target):
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_lead_details(lead, posting_date=None, company=None, doctype=None):
|
||||
def get_lead_details(
|
||||
lead: str,
|
||||
posting_date: DateTimeLikeObject | None = None,
|
||||
company: str | None = None,
|
||||
doctype: str | None = None,
|
||||
):
|
||||
if not lead:
|
||||
return {}
|
||||
|
||||
@@ -481,7 +488,7 @@ def get_lead_details(lead, posting_date=None, company=None, doctype=None):
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
def make_lead_from_communication(communication, ignore_communication_links=False):
|
||||
def make_lead_from_communication(communication: str, ignore_communication_links: bool = False):
|
||||
"""raise a issue from email"""
|
||||
|
||||
doc = frappe.get_doc("Communication", communication)
|
||||
@@ -530,7 +537,7 @@ def get_lead_with_phone_number(number):
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
def add_lead_to_prospect(lead, prospect):
|
||||
def add_lead_to_prospect(lead: str, prospect: str):
|
||||
prospect = frappe.get_doc("Prospect", prospect)
|
||||
prospect.append("leads", {"lead": lead})
|
||||
prospect.save(ignore_permissions=True)
|
||||
|
||||
@@ -307,6 +307,21 @@ erpnext.crm.Opportunity = class Opportunity extends frappe.ui.form.Controller {
|
||||
};
|
||||
});
|
||||
|
||||
this.frm.set_query("uom", "items", function (doc, cdt, cdn) {
|
||||
let row = locals[cdt][cdn];
|
||||
|
||||
if (!row.item_code) {
|
||||
return;
|
||||
}
|
||||
|
||||
return {
|
||||
query: "erpnext.controllers.queries.get_item_uom_query",
|
||||
filters: {
|
||||
item_code: row.item_code,
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
me.frm.set_query("contact_person", erpnext.queries["contact_query"]);
|
||||
|
||||
if (me.frm.doc.opportunity_from == "Lead") {
|
||||
|
||||
@@ -8,6 +8,7 @@ import frappe
|
||||
from frappe import _
|
||||
from frappe.contacts.address_and_contact import load_address_and_contact
|
||||
from frappe.email.inbox import link_communication_to_document
|
||||
from frappe.model.document import Document
|
||||
from frappe.model.mapper import get_mapped_doc
|
||||
from frappe.query_builder import DocType, Interval
|
||||
from frappe.query_builder.functions import Now
|
||||
@@ -261,7 +262,9 @@ class Opportunity(TransactionBase, CRMNote):
|
||||
self.party_name = lead_name
|
||||
|
||||
@frappe.whitelist()
|
||||
def declare_enquiry_lost(self, lost_reasons_list, competitors, detailed_reason=None):
|
||||
def declare_enquiry_lost(
|
||||
self, lost_reasons_list: list, competitors: list, detailed_reason: str | None = None
|
||||
):
|
||||
if not self.has_active_quotation():
|
||||
self.status = "Lost"
|
||||
self.lost_reasons = []
|
||||
@@ -362,7 +365,7 @@ class Opportunity(TransactionBase, CRMNote):
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_item_details(item_code):
|
||||
def get_item_details(item_code: str):
|
||||
item = frappe.db.sql(
|
||||
"""select item_name, stock_uom, image, description, item_group, brand
|
||||
from `tabItem` where name = %s""",
|
||||
@@ -380,7 +383,7 @@ def get_item_details(item_code):
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
def make_quotation(source_name, target_doc=None):
|
||||
def make_quotation(source_name: str, target_doc: str | Document | None = None):
|
||||
def set_missing_values(source, target):
|
||||
from erpnext.controllers.accounts_controller import get_default_taxes_and_charges
|
||||
|
||||
@@ -433,7 +436,7 @@ def make_quotation(source_name, target_doc=None):
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
def make_request_for_quotation(source_name, target_doc=None):
|
||||
def make_request_for_quotation(source_name: str, target_doc: str | Document | None = None):
|
||||
def update_item(obj, target, source_parent):
|
||||
target.conversion_factor = 1.0
|
||||
|
||||
@@ -455,7 +458,7 @@ def make_request_for_quotation(source_name, target_doc=None):
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
def make_customer(source_name, target_doc=None):
|
||||
def make_customer(source_name: str, target_doc: str | Document | None = None):
|
||||
def set_missing_values(source, target):
|
||||
target.opportunity_name = source.name
|
||||
|
||||
@@ -479,7 +482,7 @@ def make_customer(source_name, target_doc=None):
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
def make_supplier_quotation(source_name, target_doc=None):
|
||||
def make_supplier_quotation(source_name: str, target_doc: str | Document | None = None):
|
||||
doclist = get_mapped_doc(
|
||||
"Opportunity",
|
||||
source_name,
|
||||
@@ -494,7 +497,7 @@ def make_supplier_quotation(source_name, target_doc=None):
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
def set_multiple_status(names, status):
|
||||
def set_multiple_status(names: str | list[str], status: str):
|
||||
names = json.loads(names)
|
||||
for name in names:
|
||||
opp = frappe.get_doc("Opportunity", name)
|
||||
@@ -524,7 +527,9 @@ def auto_close_opportunity():
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
def make_opportunity_from_communication(communication, company, ignore_communication_links=False):
|
||||
def make_opportunity_from_communication(
|
||||
communication: str, company: str, ignore_communication_links: bool = False
|
||||
):
|
||||
from erpnext.crm.doctype.lead.lead import make_lead_from_communication
|
||||
|
||||
doc = frappe.get_doc("Communication", communication)
|
||||
|
||||
@@ -6,6 +6,7 @@ from frappe.contacts.address_and_contact import (
|
||||
delete_contact_and_address,
|
||||
load_address_and_contact,
|
||||
)
|
||||
from frappe.model.document import Document
|
||||
from frappe.model.mapper import get_mapped_doc
|
||||
|
||||
from erpnext.crm.utils import CRMNote, copy_comments, link_communications, link_open_events
|
||||
@@ -87,7 +88,7 @@ class Prospect(CRMNote):
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
def make_customer(source_name, target_doc=None):
|
||||
def make_customer(source_name: str, target_doc: str | Document | None = None):
|
||||
def set_missing_values(source, target):
|
||||
target.customer_type = "Company"
|
||||
target.company_name = source.name
|
||||
@@ -111,7 +112,7 @@ def make_customer(source_name, target_doc=None):
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
def make_opportunity(source_name, target_doc=None):
|
||||
def make_opportunity(source_name: str, target_doc: str | Document | None = None):
|
||||
def set_missing_values(source, target):
|
||||
target.opportunity_from = "Prospect"
|
||||
target.customer_name = source.company_name
|
||||
@@ -135,7 +136,7 @@ def make_opportunity(source_name, target_doc=None):
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_opportunities(prospect):
|
||||
def get_opportunities(prospect: str):
|
||||
return frappe.get_all(
|
||||
"Opportunity",
|
||||
filters={"opportunity_from": "Prospect", "party_name": prospect},
|
||||
|
||||
@@ -2,7 +2,7 @@ import frappe
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_last_interaction(contact=None, lead=None):
|
||||
def get_last_interaction(contact: str | None = None, lead: str | None = None):
|
||||
if not contact and not lead:
|
||||
return
|
||||
|
||||
|
||||
@@ -58,7 +58,9 @@ def create_prospect_against_crm_deal():
|
||||
)
|
||||
pass
|
||||
|
||||
create_contacts(json.loads(doc.contacts), prospect.company_name, "Prospect", prospect_name)
|
||||
if doc.contacts and len(doc.contacts):
|
||||
create_contacts(json.loads(doc.contacts), prospect.company_name, "Prospect", prospect_name)
|
||||
|
||||
create_address("Prospect", prospect_name, doc.address)
|
||||
frappe.response["message"] = prospect_name
|
||||
|
||||
@@ -149,7 +151,7 @@ def contact_exists(email, mobile_no):
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
def create_customer(customer_data=None):
|
||||
def create_customer(customer_data: dict | None = None):
|
||||
if not customer_data:
|
||||
customer_data = frappe.form_dict
|
||||
|
||||
|
||||
@@ -144,7 +144,7 @@ def link_open_events(ref_doctype, ref_docname, doc):
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_open_activities(ref_doctype, ref_docname):
|
||||
def get_open_activities(ref_doctype: str, ref_docname: str):
|
||||
tasks = get_open_todos(ref_doctype, ref_docname)
|
||||
events = get_open_events(ref_doctype, ref_docname)
|
||||
tasks_history = get_closed_todos(ref_doctype, ref_docname)
|
||||
@@ -242,20 +242,20 @@ def open_leads_opportunities_based_on_todays_event():
|
||||
|
||||
class CRMNote(Document):
|
||||
@frappe.whitelist()
|
||||
def add_note(self, note):
|
||||
def add_note(self, note: str):
|
||||
self.append("notes", {"note": note, "added_by": frappe.session.user, "added_on": now()})
|
||||
self.save()
|
||||
notify_mentions(self.doctype, self.name, note)
|
||||
|
||||
@frappe.whitelist()
|
||||
def edit_note(self, note, row_id):
|
||||
def edit_note(self, note: str, row_id: str):
|
||||
for d in self.notes:
|
||||
if cstr(d.name) == row_id:
|
||||
d.note = note
|
||||
d.db_update()
|
||||
|
||||
@frappe.whitelist()
|
||||
def delete_note(self, row_id):
|
||||
def delete_note(self, row_id: str):
|
||||
for d in self.notes:
|
||||
if cstr(d.name) == row_id:
|
||||
self.remove(d)
|
||||
|
||||
21
erpnext/desktop_icon/organization.json
Normal file
21
erpnext/desktop_icon/organization.json
Normal file
@@ -0,0 +1,21 @@
|
||||
{
|
||||
"app": "erpnext",
|
||||
"bg_color": "blue",
|
||||
"creation": "2026-02-24 17:43:08.379896",
|
||||
"docstatus": 0,
|
||||
"doctype": "Desktop Icon",
|
||||
"hidden": 0,
|
||||
"icon_type": "Link",
|
||||
"idx": 0,
|
||||
"label": "Organization",
|
||||
"link_to": "Organization",
|
||||
"link_type": "Workspace Sidebar",
|
||||
"modified": "2026-02-24 17:59:39.885360",
|
||||
"modified_by": "Administrator",
|
||||
"name": "Organization",
|
||||
"owner": "Administrator",
|
||||
"parent_icon": "",
|
||||
"restrict_removal": 0,
|
||||
"roles": [],
|
||||
"standard": 1
|
||||
}
|
||||
@@ -51,7 +51,7 @@ def get_plaid_configuration():
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
def add_institution(token, response):
|
||||
def add_institution(token: str, response: str):
|
||||
response = json.loads(response)
|
||||
|
||||
plaid = PlaidConnector()
|
||||
@@ -79,7 +79,7 @@ def add_institution(token, response):
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
def add_bank_accounts(response, bank, company):
|
||||
def add_bank_accounts(response: str | dict, bank: str | dict, company: str):
|
||||
try:
|
||||
response = json.loads(response)
|
||||
except TypeError:
|
||||
@@ -334,7 +334,7 @@ def enqueue_synchronization():
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_link_token_for_update(access_token):
|
||||
def get_link_token_for_update(access_token: str):
|
||||
plaid = PlaidConnector(access_token)
|
||||
return plaid.get_link_token(update_mode=True)
|
||||
|
||||
@@ -354,7 +354,7 @@ def get_company(bank_account_name):
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
def update_bank_account_ids(response):
|
||||
def update_bank_account_ids(response: str):
|
||||
data = json.loads(response)
|
||||
institution_name = data["institution"]["name"]
|
||||
bank = frappe.get_doc("Bank", institution_name).as_dict()
|
||||
|
||||
@@ -219,6 +219,16 @@ website_route_rules = [
|
||||
{"from_route": "/tasks", "to_route": "Task"},
|
||||
]
|
||||
|
||||
standard_navbar_items = [
|
||||
{
|
||||
"item_label": "Clear Demo Data",
|
||||
"item_type": "Action",
|
||||
"action": "erpnext.demo.clear_demo();",
|
||||
"is_standard": 1,
|
||||
"condition": "eval: frappe.boot.sysdefaults.demo_company",
|
||||
},
|
||||
]
|
||||
|
||||
standard_portal_menu_items = [
|
||||
{"title": "Projects", "route": "/project", "reference_doctype": "Project", "role": "Customer"},
|
||||
{
|
||||
|
||||
2292
erpnext/locale/es.po
2292
erpnext/locale/es.po
File diff suppressed because it is too large
Load Diff
@@ -3,7 +3,7 @@ msgstr ""
|
||||
"Project-Id-Version: frappe\n"
|
||||
"Report-Msgid-Bugs-To: hello@frappe.io\n"
|
||||
"POT-Creation-Date: 2026-02-22 09:43+0000\n"
|
||||
"PO-Revision-Date: 2026-02-24 16:58\n"
|
||||
"PO-Revision-Date: 2026-02-26 16:53\n"
|
||||
"Last-Translator: hello@frappe.io\n"
|
||||
"Language-Team: Persian\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
@@ -6996,7 +6996,7 @@ msgstr "حساب بانک / نقدی"
|
||||
#. Label of the bank_ac_no (Data) field in DocType 'Employee'
|
||||
#: erpnext/setup/doctype/employee/employee.json
|
||||
msgid "Bank A/C No."
|
||||
msgstr "شماره تهویه مطبوع بانک"
|
||||
msgstr "شماره حساب بانکی"
|
||||
|
||||
#. Name of a DocType
|
||||
#. Label of the bank_account (Link) field in DocType 'Bank Clearance'
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -3,7 +3,7 @@ msgstr ""
|
||||
"Project-Id-Version: frappe\n"
|
||||
"Report-Msgid-Bugs-To: hello@frappe.io\n"
|
||||
"POT-Creation-Date: 2026-02-22 09:43+0000\n"
|
||||
"PO-Revision-Date: 2026-02-22 16:37\n"
|
||||
"PO-Revision-Date: 2026-03-06 17:38\n"
|
||||
"Last-Translator: hello@frappe.io\n"
|
||||
"Language-Team: Russian\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
@@ -25,7 +25,12 @@ msgid "\n"
|
||||
"\t\t\tIf it is not possible to make an adjustment entry, please enable 'Allow Negative Stock for Batch' in Stock Settings to proceed.\n"
|
||||
"\t\t\tHowever, enabling this setting may lead to negative stock in the system.\n"
|
||||
"\t\t\tSo please ensure the stock levels are adjusted as soon as possible to maintain the correct valuation rate."
|
||||
msgstr ""
|
||||
msgstr "\n"
|
||||
"\t\t\tПартия {0} товара {1} имеет отрицательный остаток на складе {2}{3}.\n"
|
||||
"\t\t\tПожалуйста, добавьте количество товара {4}, чтобы продолжить ввод данных.\n"
|
||||
"\t\t\tЕсли невозможно внести корректирующие данные, пожалуйста, включите параметр «Разрешить отрицательный остаток для партии» в настройках склада, чтобы продолжить.\n"
|
||||
"\t\t\tОднако включение этого параметра может привести к отрицательному остатку в системе.\n"
|
||||
"\t\t\tПоэтому, пожалуйста, убедитесь, что уровни запасов скорректированы как можно скорее, чтобы поддерживать правильную оценочную стоимость."
|
||||
|
||||
#. Label of the column_break_32 (Column Break) field in DocType 'Email Digest'
|
||||
#: erpnext/setup/doctype/email_digest/email_digest.json
|
||||
@@ -1094,7 +1099,7 @@ msgstr "Для вас создана новая встреча с {0}"
|
||||
|
||||
#: erpnext/accounts/notification/notification_for_new_fiscal_year/notification_for_new_fiscal_year.html:3
|
||||
msgid "A new fiscal year has been automatically created."
|
||||
msgstr ""
|
||||
msgstr "Новый финансовый год был создан автоматически."
|
||||
|
||||
#: erpnext/accounts/doctype/sales_taxes_and_charges_template/sales_taxes_and_charges_template.py:96
|
||||
msgid "A template with tax category {0} already exists. Only one template is allowed with each tax category"
|
||||
@@ -1133,7 +1138,7 @@ msgstr "ACC-PINV-.YYYY.-"
|
||||
|
||||
#: erpnext/setup/doctype/transaction_deletion_record/transaction_deletion_record.js:88
|
||||
msgid "ALL records will be deleted (entire DocType cleared)"
|
||||
msgstr ""
|
||||
msgstr "ВСЕ записи будут удалены (весь DocType будет очищен)"
|
||||
|
||||
#: erpnext/stock/report/serial_no_and_batch_traceability/serial_no_and_batch_traceability.py:552
|
||||
msgid "AMC Expiry (Serial)"
|
||||
@@ -1149,7 +1154,7 @@ msgstr "Дата истечения срока действия AMC"
|
||||
#. Label of a Workspace Sidebar Item
|
||||
#: erpnext/workspace_sidebar/financial_reports.json
|
||||
msgid "AP Summary"
|
||||
msgstr ""
|
||||
msgstr "Сводка по кредиторской задолженности"
|
||||
|
||||
#. Label of the api_details_section (Section Break) field in DocType 'Currency
|
||||
#. Exchange Settings'
|
||||
@@ -4075,7 +4080,7 @@ msgstr "Разрешить отрицательный запас"
|
||||
#. Settings'
|
||||
#: erpnext/stock/doctype/stock_settings/stock_settings.json
|
||||
msgid "Allow Negative Stock for Batch"
|
||||
msgstr ""
|
||||
msgstr "Разрешить отрицательный остаток для партии"
|
||||
|
||||
#. Label of the allow_negative_rates_for_items (Check) field in DocType
|
||||
#. 'Selling Settings'
|
||||
@@ -4227,7 +4232,7 @@ msgstr "Разрешить пользователю редактировать
|
||||
#. Label of the allow_warehouse_change (Check) field in DocType 'POS Profile'
|
||||
#: erpnext/accounts/doctype/pos_profile/pos_profile.json
|
||||
msgid "Allow User to Edit Warehouse"
|
||||
msgstr ""
|
||||
msgstr "Разрешить пользователю редактировать склад"
|
||||
|
||||
#. Label of the allow_different_uom (Check) field in DocType 'Item Variant
|
||||
#. Settings'
|
||||
@@ -5943,7 +5948,7 @@ msgstr "Необходимо выбрать хотя бы один вариан
|
||||
|
||||
#: erpnext/stock/doctype/stock_entry/stock_entry.py:314
|
||||
msgid "At least one raw material item must be present in the stock entry for the type {0}"
|
||||
msgstr ""
|
||||
msgstr "Как минимум одна единица сырья должна присутствовать в записи о запасах для типа {0}"
|
||||
|
||||
#: erpnext/accounts/doctype/financial_report_template/financial_report_template.js:25
|
||||
msgid "At least one row is required for a financial report template"
|
||||
@@ -6336,7 +6341,7 @@ msgstr "Доступно"
|
||||
#. DocType 'Bin'
|
||||
#: erpnext/stock/doctype/bin/bin.json
|
||||
msgid "Available / Future Inventory"
|
||||
msgstr ""
|
||||
msgstr "Доступный / Будущий запас"
|
||||
|
||||
#. Label of the actual_batch_qty (Float) field in DocType 'Delivery Note Item'
|
||||
#: erpnext/stock/doctype/delivery_note_item/delivery_note_item.json
|
||||
@@ -7265,7 +7270,7 @@ msgstr "Банковский овердрафтовый счет"
|
||||
#. Label of a Workspace Sidebar Item
|
||||
#: erpnext/workspace_sidebar/banking.json
|
||||
msgid "Bank Reconciliation"
|
||||
msgstr ""
|
||||
msgstr "Инвентаризация банковских счетов"
|
||||
|
||||
#. Name of a report
|
||||
#. Label of a Link in the Invoicing Workspace
|
||||
@@ -8459,7 +8464,7 @@ msgstr "Дата начала бюджета"
|
||||
#. Label of a Workspace Sidebar Item
|
||||
#: erpnext/workspace_sidebar/budget.json
|
||||
msgid "Budget Variance"
|
||||
msgstr ""
|
||||
msgstr "Отклонение от бюджета"
|
||||
|
||||
#. Name of a report
|
||||
#. Label of a Link in the Invoicing Workspace
|
||||
@@ -8653,7 +8658,7 @@ msgstr "Копия для"
|
||||
#. Label of a Workspace Sidebar Item
|
||||
#: erpnext/workspace_sidebar/accounts_setup.json
|
||||
msgid "COA Importer"
|
||||
msgstr ""
|
||||
msgstr "Импорт плана счетов"
|
||||
|
||||
#. Option for the 'Barcode Type' (Select) field in DocType 'Item Barcode'
|
||||
#: erpnext/stock/doctype/item_barcode/item_barcode.json
|
||||
@@ -8937,7 +8942,7 @@ msgstr "Графики кампаний"
|
||||
|
||||
#: erpnext/crm/doctype/email_campaign/email_campaign.py:113
|
||||
msgid "Campaign {0} not found"
|
||||
msgstr ""
|
||||
msgstr "Кампания {0} не найдена"
|
||||
|
||||
#: erpnext/setup/doctype/authorization_control/authorization_control.py:60
|
||||
msgid "Can be approved by {0}"
|
||||
@@ -9052,7 +9057,7 @@ msgstr "Невозможно повторно отправить записи в
|
||||
|
||||
#: erpnext/setup/doctype/transaction_deletion_record/transaction_deletion_record.py:202
|
||||
msgid "Cannot add child table {0} to deletion list. Child tables are automatically deleted with their parent DocTypes."
|
||||
msgstr ""
|
||||
msgstr "Невозможно добавить дочернюю таблицу {0} в список для удаления. Дочерние таблицы автоматически удаляются вместе с родительскими DocType."
|
||||
|
||||
#: erpnext/stock/doctype/stock_reservation_entry/stock_reservation_entry.py:226
|
||||
msgid "Cannot amend {0} {1}, please create a new one instead."
|
||||
@@ -9195,7 +9200,7 @@ msgstr ""
|
||||
|
||||
#: erpnext/setup/doctype/transaction_deletion_record/transaction_deletion_record.py:211
|
||||
msgid "Cannot delete virtual DocType: {0}. Virtual DocTypes do not have database tables."
|
||||
msgstr ""
|
||||
msgstr "Невозможно удалить виртуальный DocType: {0}. Виртуальные DocType не имеют таблиц в базе данных."
|
||||
|
||||
#: erpnext/setup/doctype/company/company.py:559
|
||||
msgid "Cannot disable perpetual inventory, as there are existing Stock Ledger Entries for the company {0}. Please cancel the stock transactions first and try again."
|
||||
@@ -9232,7 +9237,7 @@ msgstr "Невозможно объединить {0} '{1}' с '{2}', поско
|
||||
|
||||
#: erpnext/manufacturing/doctype/work_order/work_order.py:543
|
||||
msgid "Cannot produce more Item {0} than Sales Order quantity {1} {2}"
|
||||
msgstr ""
|
||||
msgstr "Невозможно произвести больше товаров {0}, чем количество товаров в заказе на продажу {1} {2}"
|
||||
|
||||
#: erpnext/manufacturing/doctype/work_order/work_order.py:1439
|
||||
msgid "Cannot produce more item for {0}"
|
||||
@@ -9287,7 +9292,7 @@ msgstr "Невозможно установить несколько парам
|
||||
|
||||
#: erpnext/assets/doctype/asset_category/asset_category.py:108
|
||||
msgid "Cannot set multiple account rows for the same company"
|
||||
msgstr ""
|
||||
msgstr "Невозможно задать несколько счетов для одной и той же компании"
|
||||
|
||||
#: erpnext/controllers/accounts_controller.py:3885
|
||||
msgid "Cannot set quantity less than delivered quantity"
|
||||
@@ -9303,7 +9308,7 @@ msgstr "Невозможно установить поле <b>{0}</b> для к
|
||||
|
||||
#: erpnext/setup/doctype/transaction_deletion_record/transaction_deletion_record.py:264
|
||||
msgid "Cannot start deletion. Another deletion {0} is already queued/running. Please wait for it to complete."
|
||||
msgstr ""
|
||||
msgstr "Невозможно начать удаление. Другое удаление {0} уже находится в очереди/выполняется. Пожалуйста, дождитесь его завершения."
|
||||
|
||||
#: erpnext/accounts/doctype/payment_entry/payment_entry.py:1920
|
||||
msgid "Cannot {0} from {1} without any negative outstanding invoice"
|
||||
@@ -9945,7 +9950,7 @@ msgstr "Технический директор"
|
||||
#. Deletion Record To Delete'
|
||||
#: erpnext/setup/doctype/transaction_deletion_record_to_delete/transaction_deletion_record_to_delete.json
|
||||
msgid "Child DocTypes"
|
||||
msgstr ""
|
||||
msgstr "Дочерние типы документов"
|
||||
|
||||
#. Label of the child_docname (Data) field in DocType 'Pricing Rule Detail'
|
||||
#: erpnext/accounts/doctype/pricing_rule_detail/pricing_rule_detail.json
|
||||
@@ -9961,7 +9966,7 @@ msgstr "Ссылка на дочернюю строку"
|
||||
|
||||
#: erpnext/setup/doctype/transaction_deletion_record/transaction_deletion_record.py:205
|
||||
msgid "Child Table Not Allowed"
|
||||
msgstr ""
|
||||
msgstr "Дочерняя таблица не допускается"
|
||||
|
||||
#: erpnext/projects/doctype/task/task.py:312
|
||||
msgid "Child Task exists for this Task. You can not delete this Task."
|
||||
@@ -9975,7 +9980,7 @@ msgstr "Дочерние узлы могут быть созданы тольк
|
||||
#. 'Transaction Deletion Record To Delete'
|
||||
#: erpnext/setup/doctype/transaction_deletion_record_to_delete/transaction_deletion_record_to_delete.json
|
||||
msgid "Child tables that will also be deleted"
|
||||
msgstr ""
|
||||
msgstr "Дочерние таблицы, которые также будут удалены"
|
||||
|
||||
#: erpnext/stock/doctype/warehouse/warehouse.py:103
|
||||
msgid "Child warehouse exists for this warehouse. You can not delete this warehouse."
|
||||
@@ -10833,7 +10838,7 @@ msgstr "Счет компании"
|
||||
|
||||
#: erpnext/accounts/doctype/bank_account/bank_account.py:63
|
||||
msgid "Company Account is mandatory"
|
||||
msgstr ""
|
||||
msgstr "Счет компании обязателен"
|
||||
|
||||
#. Label of the company_address (Link) field in DocType 'Dunning'
|
||||
#. Label of the company_address_display (Text Editor) field in DocType 'POS
|
||||
@@ -10950,7 +10955,7 @@ msgstr "Электронная почта компании"
|
||||
#. Record To Delete'
|
||||
#: erpnext/setup/doctype/transaction_deletion_record_to_delete/transaction_deletion_record_to_delete.json
|
||||
msgid "Company Field"
|
||||
msgstr ""
|
||||
msgstr "Поле компании"
|
||||
|
||||
#. Label of the company_logo (Attach Image) field in DocType 'Company'
|
||||
#: erpnext/public/js/print.js:64 erpnext/setup/doctype/company/company.json
|
||||
@@ -11004,7 +11009,7 @@ msgstr "Компания обязательна для создания счет
|
||||
#. Deletion Record To Delete'
|
||||
#: erpnext/setup/doctype/transaction_deletion_record_to_delete/transaction_deletion_record_to_delete.json
|
||||
msgid "Company link field name used for filtering (optional - leave empty to delete all records)"
|
||||
msgstr ""
|
||||
msgstr "Название поля ссылки на компанию, используемое для фильтрации (необязательно — оставьте пустым, чтобы удалить все записи)"
|
||||
|
||||
#: erpnext/setup/doctype/company/company.js:222
|
||||
msgid "Company name not same"
|
||||
@@ -11197,12 +11202,12 @@ msgstr "Наименование компонента"
|
||||
#. Option for the 'Asset Type' (Select) field in DocType 'Asset'
|
||||
#: erpnext/assets/doctype/asset/asset.json
|
||||
msgid "Composite Asset"
|
||||
msgstr ""
|
||||
msgstr "Составной актив"
|
||||
|
||||
#. Option for the 'Asset Type' (Select) field in DocType 'Asset'
|
||||
#: erpnext/assets/doctype/asset/asset.json
|
||||
msgid "Composite Component"
|
||||
msgstr ""
|
||||
msgstr "Составной компонент"
|
||||
|
||||
#. Label of the comprehensive_insurance (Data) field in DocType 'Asset'
|
||||
#: erpnext/assets/doctype/asset/asset.json
|
||||
@@ -11261,7 +11266,7 @@ msgstr "Дата подтверждения"
|
||||
#. Label of the connection_tab (Tab Break) field in DocType 'Asset Repair'
|
||||
#: erpnext/assets/doctype/asset_repair/asset_repair.json
|
||||
msgid "Connection"
|
||||
msgstr ""
|
||||
msgstr "Подключение"
|
||||
|
||||
#: erpnext/accounts/report/general_ledger/general_ledger.js:175
|
||||
msgid "Consider Accounting Dimensions"
|
||||
@@ -11361,7 +11366,7 @@ msgstr "Консолидированный финансовый отчет"
|
||||
#. Label of a Workspace Sidebar Item
|
||||
#: erpnext/workspace_sidebar/financial_reports.json
|
||||
msgid "Consolidated Report"
|
||||
msgstr ""
|
||||
msgstr "Сводный отчет"
|
||||
|
||||
#. Label of the consolidated_invoice (Link) field in DocType 'POS Invoice'
|
||||
#. Label of the consolidated_invoice (Link) field in DocType 'POS Invoice Merge
|
||||
@@ -13717,7 +13722,7 @@ msgstr "Номер клиента LPO"
|
||||
#. Label of a Workspace Sidebar Item
|
||||
#: erpnext/workspace_sidebar/financial_reports.json
|
||||
msgid "Customer Ledger"
|
||||
msgstr ""
|
||||
msgstr "Клиентская книга"
|
||||
|
||||
#. Name of a report
|
||||
#. Label of a Link in the Financial Reports Workspace
|
||||
@@ -13831,7 +13836,7 @@ msgstr "Подробности заказа клиента"
|
||||
#. Label of the customer_pos_id (Data) field in DocType 'Customer'
|
||||
#: erpnext/selling/doctype/customer/customer.json
|
||||
msgid "Customer POS ID"
|
||||
msgstr ""
|
||||
msgstr "Идентификатор клиента точки продаж"
|
||||
|
||||
#. Label of the portal_users (Table) field in DocType 'Customer'
|
||||
#: erpnext/selling/doctype/customer/customer.json
|
||||
@@ -15141,11 +15146,11 @@ msgstr "Для страны не разрешено удаление {0}"
|
||||
|
||||
#: erpnext/setup/doctype/transaction_deletion_record/transaction_deletion_record.js:216
|
||||
msgid "Deletion process restarted"
|
||||
msgstr ""
|
||||
msgstr "Процесс удаления перезапущен"
|
||||
|
||||
#: erpnext/setup/doctype/transaction_deletion_record/transaction_deletion_record.js:97
|
||||
msgid "Deletion will start automatically after submission."
|
||||
msgstr ""
|
||||
msgstr "Удаление начнётся автоматически после отправки."
|
||||
|
||||
#. Label of the delimiter_options (Data) field in DocType 'Bank Statement
|
||||
#. Import'
|
||||
@@ -16602,27 +16607,27 @@ msgstr "DocType {0} не существует"
|
||||
|
||||
#: erpnext/setup/doctype/transaction_deletion_record/transaction_deletion_record.js:295
|
||||
msgid "DocType {0} with company field '{1}' is already in the list"
|
||||
msgstr ""
|
||||
msgstr "DocType {0} с полем компании '{1}' уже есть в списке"
|
||||
|
||||
#. Label of the doctypes_to_delete (Table) field in DocType 'Transaction
|
||||
#. Deletion Record'
|
||||
#: erpnext/setup/doctype/transaction_deletion_record/transaction_deletion_record.json
|
||||
msgid "DocTypes To Delete"
|
||||
msgstr ""
|
||||
msgstr "DocType для удаления"
|
||||
|
||||
#. Description of the 'Excluded DocTypes' (Table) field in DocType 'Transaction
|
||||
#. Deletion Record'
|
||||
#: erpnext/setup/doctype/transaction_deletion_record/transaction_deletion_record.json
|
||||
msgid "DocTypes that will NOT be deleted."
|
||||
msgstr ""
|
||||
msgstr "DocType, которые НЕ будут удалены."
|
||||
|
||||
#: erpnext/setup/doctype/transaction_deletion_record/transaction_deletion_record.js:84
|
||||
msgid "DocTypes with a company field:"
|
||||
msgstr ""
|
||||
msgstr "DocTypes с полем \"Компания\":"
|
||||
|
||||
#: erpnext/setup/doctype/transaction_deletion_record/transaction_deletion_record.js:88
|
||||
msgid "DocTypes without a company field:"
|
||||
msgstr ""
|
||||
msgstr "Типы документов без поля \"Компания\":"
|
||||
|
||||
#: erpnext/templates/pages/search_help.py:22
|
||||
msgid "Docs Search"
|
||||
@@ -16632,11 +16637,11 @@ msgstr "Поиск документов"
|
||||
#. Record To Delete'
|
||||
#: erpnext/setup/doctype/transaction_deletion_record_to_delete/transaction_deletion_record_to_delete.json
|
||||
msgid "Document Count"
|
||||
msgstr ""
|
||||
msgstr "Количество документов"
|
||||
|
||||
#: erpnext/stock/report/negative_batch_report/negative_batch_report.py:78
|
||||
msgid "Document No"
|
||||
msgstr ""
|
||||
msgstr "Документ №"
|
||||
|
||||
#. Label of the document_type (Link) field in DocType 'Subscription Invoice'
|
||||
#: erpnext/accounts/doctype/subscription_invoice/subscription_invoice.json
|
||||
@@ -16899,7 +16904,7 @@ msgstr "Дублировать группу клиентов"
|
||||
|
||||
#: erpnext/setup/doctype/transaction_deletion_record/transaction_deletion_record.py:188
|
||||
msgid "Duplicate DocType"
|
||||
msgstr ""
|
||||
msgstr "Дублирование DocType"
|
||||
|
||||
#: erpnext/setup/doctype/authorization_rule/authorization_rule.py:71
|
||||
msgid "Duplicate Entry. Please check Authorization Rule {0}"
|
||||
@@ -16957,7 +16962,7 @@ msgstr "Повторяющаяся запись с кодом товара {0}
|
||||
|
||||
#: erpnext/setup/doctype/transaction_deletion_record/transaction_deletion_record.py:187
|
||||
msgid "Duplicate entry: {0}{1}"
|
||||
msgstr ""
|
||||
msgstr "Повторяющаяся запись: {0}{1}"
|
||||
|
||||
#: erpnext/accounts/doctype/pos_profile/pos_profile.py:165
|
||||
msgid "Duplicate item group found in the item group table"
|
||||
@@ -17230,7 +17235,7 @@ msgstr "Кампания по электронной почте"
|
||||
#: erpnext/crm/doctype/email_campaign/email_campaign.py:149
|
||||
#: erpnext/crm/doctype/email_campaign/email_campaign.py:157
|
||||
msgid "Email Campaign Error"
|
||||
msgstr ""
|
||||
msgstr "Ошибка кампании электронной почты"
|
||||
|
||||
#. Label of the email_campaign_for (Select) field in DocType 'Email Campaign'
|
||||
#: erpnext/crm/doctype/email_campaign/email_campaign.json
|
||||
@@ -17239,7 +17244,7 @@ msgstr "Email-кампания для"
|
||||
|
||||
#: erpnext/crm/doctype/email_campaign/email_campaign.py:125
|
||||
msgid "Email Campaign Send Error"
|
||||
msgstr ""
|
||||
msgstr "Ошибка отправки кампании электронной почты"
|
||||
|
||||
#. Label of the supplier_response_section (Section Break) field in DocType
|
||||
#. 'Request for Quotation'
|
||||
@@ -17490,7 +17495,7 @@ msgstr "Пустой"
|
||||
|
||||
#: erpnext/setup/doctype/transaction_deletion_record/transaction_deletion_record.py:752
|
||||
msgid "Empty To Delete List"
|
||||
msgstr ""
|
||||
msgstr "Пустой список для удаления"
|
||||
|
||||
#. Name of a UOM
|
||||
#: erpnext/setup/setup_wizard/data/uom_data.json
|
||||
@@ -17576,7 +17581,7 @@ msgstr "Включить учет скидок при продаже"
|
||||
#. Settings'
|
||||
#: erpnext/accounts/doctype/accounts_settings/accounts_settings.json
|
||||
msgid "Enable Discounts and Margin"
|
||||
msgstr ""
|
||||
msgstr "Включить скидки и наценку"
|
||||
|
||||
#. Label of the enable_european_access (Check) field in DocType 'Plaid
|
||||
#. Settings'
|
||||
@@ -17640,7 +17645,7 @@ msgstr "Включить резервирование запасов"
|
||||
#. Label of the enable_utm (Check) field in DocType 'Selling Settings'
|
||||
#: erpnext/selling/doctype/selling_settings/selling_settings.json
|
||||
msgid "Enable UTM"
|
||||
msgstr ""
|
||||
msgstr "Включить UTM"
|
||||
|
||||
#. Description of the 'Enable UTM' (Check) field in DocType 'Selling Settings'
|
||||
#: erpnext/selling/doctype/selling_settings/selling_settings.json
|
||||
@@ -18695,7 +18700,7 @@ msgstr "Не удалось провести записи по амортиза
|
||||
|
||||
#: erpnext/crm/doctype/email_campaign/email_campaign.py:126
|
||||
msgid "Failed to send email for campaign {0} to {1}"
|
||||
msgstr ""
|
||||
msgstr "Не удалось отправить электронное письмо для кампании {0} на адрес {1}"
|
||||
|
||||
#: erpnext/setup/setup_wizard/setup_wizard.py:30
|
||||
#: erpnext/setup/setup_wizard/setup_wizard.py:31
|
||||
@@ -18749,7 +18754,7 @@ msgstr "Отзыв от"
|
||||
#. Label of a Workspace Sidebar Item
|
||||
#: erpnext/workspace_sidebar/quality.json
|
||||
msgid "Feedback Template"
|
||||
msgstr ""
|
||||
msgstr "Шаблон обратной связи"
|
||||
|
||||
#. Option for the 'Reference Type' (Select) field in DocType 'Journal Entry
|
||||
#. Account'
|
||||
@@ -18837,7 +18842,7 @@ msgstr "Получение данных..."
|
||||
|
||||
#: erpnext/setup/doctype/transaction_deletion_record/transaction_deletion_record.py:222
|
||||
msgid "Field '{0}' is not a valid Company link field for DocType {1}"
|
||||
msgstr ""
|
||||
msgstr "Поле '{0}' не является действительным полем ссылки на компанию для DocType {1}"
|
||||
|
||||
#. Label of the field_mapping_section (Section Break) field in DocType
|
||||
#. 'Inventory Dimension'
|
||||
@@ -18859,15 +18864,15 @@ msgstr "Поля будут скопированы только во время
|
||||
|
||||
#: erpnext/setup/doctype/transaction_deletion_record/transaction_deletion_record.py:1064
|
||||
msgid "File does not belong to this Transaction Deletion Record"
|
||||
msgstr ""
|
||||
msgstr "Файл не относится к данной записи об удалении транзакции"
|
||||
|
||||
#: erpnext/setup/doctype/transaction_deletion_record/transaction_deletion_record.py:1058
|
||||
msgid "File not found"
|
||||
msgstr ""
|
||||
msgstr "Файл не найден"
|
||||
|
||||
#: erpnext/setup/doctype/transaction_deletion_record/transaction_deletion_record.py:1072
|
||||
msgid "File not found on server"
|
||||
msgstr ""
|
||||
msgstr "Файл не найден на сервере"
|
||||
|
||||
#. Label of the file_to_rename (Attach) field in DocType 'Rename Tool'
|
||||
#: erpnext/utilities/doctype/rename_tool/rename_tool.json
|
||||
@@ -19322,7 +19327,7 @@ msgstr "Финансовый год компании"
|
||||
|
||||
#: erpnext/accounts/notification/notification_for_new_fiscal_year/notification_for_new_fiscal_year.html:5
|
||||
msgid "Fiscal Year Details"
|
||||
msgstr ""
|
||||
msgstr "Подробная информация о финансовом году"
|
||||
|
||||
#: erpnext/accounts/doctype/fiscal_year/fiscal_year.py:47
|
||||
msgid "Fiscal Year End Date should be one year after Fiscal Year Start Date"
|
||||
@@ -19638,7 +19643,7 @@ msgstr "Для элемента {0} ставка должна быть поло
|
||||
|
||||
#: erpnext/manufacturing/doctype/bom/bom.py:347
|
||||
msgid "For operation {0} at row {1}, please add raw materials or set a BOM against it."
|
||||
msgstr ""
|
||||
msgstr "Для операции {0} в строке {1} добавьте сырье или создайте спецификацию материалов для нее."
|
||||
|
||||
#: erpnext/manufacturing/doctype/work_order/work_order.py:2591
|
||||
msgid "For operation {0}: Quantity ({1}) can not be greater than pending quantity({2})"
|
||||
@@ -19692,7 +19697,7 @@ msgstr "Для удобства клиентов эти коды можно ис
|
||||
|
||||
#: erpnext/stock/doctype/stock_entry/stock_entry.py:978
|
||||
msgid "For the item {0}, the consumed quantity should be {1} according to the BOM {2}."
|
||||
msgstr ""
|
||||
msgstr "Для изделия {0} количество потребленного материала должно быть {1} согласно спецификации материалов {2}."
|
||||
|
||||
#: erpnext/public/js/controllers/transaction.js:1299
|
||||
msgctxt "Clear payment terms template and/or payment schedule when due date is changed"
|
||||
@@ -20198,7 +20203,7 @@ msgstr "Условия и положения выполнения"
|
||||
|
||||
#: erpnext/stock/doctype/shipment/shipment.js:275
|
||||
msgid "Full Name, Email or Phone/Mobile of the user are mandatory to continue."
|
||||
msgstr ""
|
||||
msgstr "Для продолжения необходимо указать полное имя, адрес электронной почты или номер телефона/мобильного телефона пользователя."
|
||||
|
||||
#. Option for the 'Reference Type' (Select) field in DocType 'Journal Entry
|
||||
#. Account'
|
||||
@@ -20476,11 +20481,11 @@ msgstr "Создать запись закрытия складского зап
|
||||
|
||||
#: erpnext/setup/doctype/transaction_deletion_record/transaction_deletion_record.js:112
|
||||
msgid "Generate To Delete List"
|
||||
msgstr ""
|
||||
msgstr "Создать список для удаления"
|
||||
|
||||
#: erpnext/setup/doctype/transaction_deletion_record/transaction_deletion_record.py:470
|
||||
msgid "Generate To Delete list first"
|
||||
msgstr ""
|
||||
msgstr "Сначала сгенерируйте список для удаления"
|
||||
|
||||
#. Description of a DocType
|
||||
#: erpnext/stock/doctype/packing_slip/packing_slip.json
|
||||
@@ -30013,7 +30018,7 @@ msgstr "Новые расходы"
|
||||
|
||||
#: erpnext/accounts/notification/notification_for_new_fiscal_year/notification_for_new_fiscal_year.html:1
|
||||
msgid "New Fiscal Year - {0}"
|
||||
msgstr ""
|
||||
msgstr "Новый финансовый год - {0}"
|
||||
|
||||
#. Label of the income (Check) field in DocType 'Email Digest'
|
||||
#: erpnext/setup/doctype/email_digest/email_digest.json
|
||||
@@ -30183,7 +30188,7 @@ msgstr "Нет примечания о доставке для клиента {}
|
||||
|
||||
#: erpnext/setup/doctype/transaction_deletion_record/transaction_deletion_record.py:751
|
||||
msgid "No DocTypes in To Delete list. Please generate or import the list before submitting."
|
||||
msgstr ""
|
||||
msgstr "В списке «Для удаления» нет DocTypes. Пожалуйста, сгенерируйте или импортируйте список перед отправкой."
|
||||
|
||||
#: erpnext/public/js/utils/ledger_preview.js:64
|
||||
msgid "No Impact on Accounting Ledger"
|
||||
@@ -30203,7 +30208,7 @@ msgstr "Не выбрано ни одного товара для передач
|
||||
|
||||
#: erpnext/selling/doctype/sales_order/sales_order.js:1226
|
||||
msgid "No Items with Bill of Materials to Manufacture or all items already manufactured"
|
||||
msgstr ""
|
||||
msgstr "Нет товаров, для которых имеется спецификация материалов для производства, или все товары уже изготовлены"
|
||||
|
||||
#: erpnext/selling/doctype/sales_order/sales_order.js:1372
|
||||
msgid "No Items with Bill of Materials."
|
||||
@@ -30334,7 +30339,7 @@ msgstr "Различий по складскому счёту {0} не обна
|
||||
|
||||
#: erpnext/crm/doctype/email_campaign/email_campaign.py:150
|
||||
msgid "No email found for {0} {1}"
|
||||
msgstr ""
|
||||
msgstr "Адрес электронной почты для {0} {1} не найден"
|
||||
|
||||
#: erpnext/telephony/doctype/call_log/call_log.py:117
|
||||
msgid "No employee was scheduled for call popup"
|
||||
@@ -30489,7 +30494,7 @@ msgstr "Не найдено принятых транзакций"
|
||||
|
||||
#: erpnext/crm/doctype/email_campaign/email_campaign.py:158
|
||||
msgid "No recipients found for campaign {0}"
|
||||
msgstr ""
|
||||
msgstr "Получателей для кампании {0} не найдено."
|
||||
|
||||
#: erpnext/accounts/report/purchase_register/purchase_register.py:45
|
||||
#: erpnext/accounts/report/sales_register/sales_register.py:46
|
||||
@@ -30515,7 +30520,7 @@ msgstr "Нет зарезервированных запасов для отме
|
||||
|
||||
#: erpnext/setup/doctype/transaction_deletion_record/transaction_deletion_record.js:152
|
||||
msgid "No rows with zero document count found"
|
||||
msgstr ""
|
||||
msgstr "Строки с нулевым количеством документов не найдены"
|
||||
|
||||
#: erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.py:804
|
||||
msgid "No stock ledger entries were created. Please set the quantity or valuation rate for the items properly and try again."
|
||||
@@ -31121,7 +31126,7 @@ msgstr "Для импорта данных можно использовать
|
||||
|
||||
#: erpnext/setup/doctype/transaction_deletion_record/transaction_deletion_record.py:1067
|
||||
msgid "Only CSV files are allowed"
|
||||
msgstr ""
|
||||
msgstr "Разрешается использовать только CSV-файлы"
|
||||
|
||||
#. Label of the tax_on_excess_amount (Check) field in DocType 'Tax Withholding
|
||||
#. Category'
|
||||
@@ -31438,7 +31443,7 @@ msgstr "Открытие счета"
|
||||
#. Label of a Workspace Sidebar Item
|
||||
#: erpnext/workspace_sidebar/accounts_setup.json
|
||||
msgid "Opening Invoice Tool"
|
||||
msgstr ""
|
||||
msgstr "Инструмент для открытия счета-фактуры"
|
||||
|
||||
#: erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py:1646
|
||||
#: erpnext/accounts/doctype/sales_invoice/sales_invoice.py:1990
|
||||
@@ -32209,7 +32214,7 @@ msgstr "Внешний"
|
||||
#. Label of a Workspace Sidebar Item
|
||||
#: erpnext/workspace_sidebar/subcontracting.json
|
||||
msgid "Outward Order"
|
||||
msgstr ""
|
||||
msgstr "Исходящий заказ"
|
||||
|
||||
#. Label of the over_billing_allowance (Currency) field in DocType 'Accounts
|
||||
#. Settings'
|
||||
@@ -32362,7 +32367,7 @@ msgstr "Владелец"
|
||||
#. Label of the asset_owner_section (Section Break) field in DocType 'Asset'
|
||||
#: erpnext/assets/doctype/asset/asset.json
|
||||
msgid "Ownership"
|
||||
msgstr ""
|
||||
msgstr "Собственность"
|
||||
|
||||
#. Label of the p_l_closing_balance (JSON) field in DocType 'Process Period
|
||||
#. Closing Voucher'
|
||||
@@ -32457,7 +32462,7 @@ msgstr "Закрытие точки продаж не удалось при вы
|
||||
#. Profile'
|
||||
#: erpnext/accounts/doctype/pos_profile/pos_profile.json
|
||||
msgid "POS Configurations"
|
||||
msgstr ""
|
||||
msgstr "Настройки POS"
|
||||
|
||||
#. Name of a DocType
|
||||
#: erpnext/accounts/doctype/pos_customer_group/pos_customer_group.json
|
||||
@@ -33857,7 +33862,7 @@ msgstr "Режим платежа"
|
||||
#. 'Accounts Settings'
|
||||
#: erpnext/accounts/doctype/accounts_settings/accounts_settings.json
|
||||
msgid "Payment Options"
|
||||
msgstr ""
|
||||
msgstr "Варианты оплаты"
|
||||
|
||||
#. Label of the payment_order (Link) field in DocType 'Journal Entry'
|
||||
#. Label of the payment_order (Link) field in DocType 'Payment Entry'
|
||||
@@ -33924,7 +33929,7 @@ msgstr "Платеж получен"
|
||||
#. Label of a Workspace Sidebar Item
|
||||
#: erpnext/workspace_sidebar/payments.json
|
||||
msgid "Payment Reconciliaition"
|
||||
msgstr ""
|
||||
msgstr "Сверка платежей"
|
||||
|
||||
#. Name of a DocType
|
||||
#. Label of the payment_reconciliation (Table) field in DocType 'POS Closing
|
||||
@@ -35257,7 +35262,7 @@ msgstr "Пожалуйста, введите утверждении роли и
|
||||
|
||||
#: erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.py:677
|
||||
msgid "Please enter Batch No"
|
||||
msgstr ""
|
||||
msgstr "Пожалуйста, введите номер партии"
|
||||
|
||||
#: erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.py:970
|
||||
msgid "Please enter Cost Center"
|
||||
@@ -35322,7 +35327,7 @@ msgstr "Пожалуйста, укажите корневой тип для сч
|
||||
|
||||
#: erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.py:679
|
||||
msgid "Please enter Serial No"
|
||||
msgstr ""
|
||||
msgstr "Пожалуйста, введите серийный номер"
|
||||
|
||||
#: erpnext/public/js/utils/serial_no_batch_selector.js:309
|
||||
msgid "Please enter Serial Nos"
|
||||
@@ -35423,7 +35428,7 @@ msgstr "Пожалуйста, заполните таблицу заказов
|
||||
|
||||
#: erpnext/stock/doctype/shipment/shipment.js:277
|
||||
msgid "Please first set Full Name, Email and Phone for the user"
|
||||
msgstr ""
|
||||
msgstr "Пожалуйста, сначала укажите полное имя, адрес электронной почты и номер телефона пользователя"
|
||||
|
||||
#: erpnext/telephony/doctype/incoming_call_settings/incoming_call_settings.js:94
|
||||
msgid "Please fix overlapping time slots for {0}"
|
||||
@@ -35435,11 +35440,11 @@ msgstr "Пожалуйста, исправьте накладывающиеся
|
||||
|
||||
#: erpnext/setup/doctype/transaction_deletion_record/transaction_deletion_record.py:270
|
||||
msgid "Please generate To Delete list before submitting"
|
||||
msgstr ""
|
||||
msgstr "Пожалуйста, сгенерируйте список для удаления перед проведением"
|
||||
|
||||
#: erpnext/setup/doctype/transaction_deletion_record/transaction_deletion_record.js:70
|
||||
msgid "Please generate the To Delete list before submitting"
|
||||
msgstr ""
|
||||
msgstr "Пожалуйста, сгенерируйте список для удаления перед проведением"
|
||||
|
||||
#: erpnext/accounts/doctype/chart_of_accounts_importer/chart_of_accounts_importer.py:67
|
||||
msgid "Please import accounts against parent company or enable {} in company master."
|
||||
@@ -35488,7 +35493,7 @@ msgstr "Пожалуйста, обновите или сбросьте прив
|
||||
|
||||
#: erpnext/accounts/notification/notification_for_new_fiscal_year/notification_for_new_fiscal_year.html:43
|
||||
msgid "Please review the {0} configuration and complete any required financial setup activities."
|
||||
msgstr ""
|
||||
msgstr "Пожалуйста, проверьте конфигурацию {0} и выполните все необходимые действия по настройке финансовых параметров."
|
||||
|
||||
#: erpnext/accounts/doctype/process_statement_of_accounts/process_statement_of_accounts.js:12
|
||||
#: erpnext/accounts/doctype/process_statement_of_accounts/process_statement_of_accounts.js:28
|
||||
@@ -36577,7 +36582,7 @@ msgstr "Предыдущий финансовый год не закрыт"
|
||||
|
||||
#: erpnext/stock/report/negative_batch_report/negative_batch_report.py:54
|
||||
msgid "Previous Qty"
|
||||
msgstr ""
|
||||
msgstr "Предыдущее количество"
|
||||
|
||||
#. Label of the previous_work_experience (Section Break) field in DocType
|
||||
#. 'Employee'
|
||||
@@ -36667,7 +36672,7 @@ msgstr "Прайс-лист"
|
||||
#. DocType 'POS Profile'
|
||||
#: erpnext/accounts/doctype/pos_profile/pos_profile.json
|
||||
msgid "Price List & Currency"
|
||||
msgstr ""
|
||||
msgstr "Прайс-лист и валюта"
|
||||
|
||||
#. Name of a DocType
|
||||
#: erpnext/stock/doctype/price_list_country/price_list_country.json
|
||||
@@ -37325,7 +37330,7 @@ msgstr "Обработка файлов XML"
|
||||
|
||||
#: erpnext/setup/doctype/transaction_deletion_record/transaction_deletion_record.js:188
|
||||
msgid "Processing import..."
|
||||
msgstr ""
|
||||
msgstr "Обработка импорта..."
|
||||
|
||||
#: erpnext/buying/doctype/supplier/supplier_dashboard.py:10
|
||||
msgid "Procurement"
|
||||
@@ -37503,7 +37508,7 @@ msgstr "Производство товара"
|
||||
#: erpnext/manufacturing/doctype/bom/bom.json
|
||||
#: erpnext/manufacturing/doctype/work_order/work_order.json
|
||||
msgid "Production Item Info"
|
||||
msgstr ""
|
||||
msgstr "Информация о товаре"
|
||||
|
||||
#. Label of the production_plan (Link) field in DocType 'Purchase Order Item'
|
||||
#. Name of a DocType
|
||||
@@ -38003,7 +38008,7 @@ msgstr "Перспективные, но не работающие"
|
||||
#: erpnext/setup/doctype/transaction_deletion_record/transaction_deletion_record.py:196
|
||||
#: erpnext/setup/doctype/transaction_deletion_record/transaction_deletion_record.py:781
|
||||
msgid "Protected DocType"
|
||||
msgstr ""
|
||||
msgstr "Защищенный DocType"
|
||||
|
||||
#. Description of the 'Company Email' (Data) field in DocType 'Employee'
|
||||
#: erpnext/setup/doctype/employee/employee.json
|
||||
@@ -39205,17 +39210,17 @@ msgstr "Название шаблона проверки качества"
|
||||
|
||||
#: erpnext/manufacturing/doctype/job_card/job_card.py:782
|
||||
msgid "Quality Inspection is required for the item {0} before completing the job card {1}"
|
||||
msgstr ""
|
||||
msgstr "Перед заполнением накладной {1} необходимо провести контроль качества изделия {0}"
|
||||
|
||||
#: erpnext/manufacturing/doctype/job_card/job_card.py:793
|
||||
#: erpnext/manufacturing/doctype/job_card/job_card.py:802
|
||||
msgid "Quality Inspection {0} is not submitted for the item: {1}"
|
||||
msgstr ""
|
||||
msgstr "Контроль качества {0} не проведён для товара: {1}"
|
||||
|
||||
#: erpnext/manufacturing/doctype/job_card/job_card.py:812
|
||||
#: erpnext/manufacturing/doctype/job_card/job_card.py:821
|
||||
msgid "Quality Inspection {0} is rejected for the item: {1}"
|
||||
msgstr ""
|
||||
msgstr "Контроль качества {0} отклоняется для изделия: {1}"
|
||||
|
||||
#: erpnext/public/js/controllers/transaction.js:384
|
||||
#: erpnext/stock/doctype/stock_entry/stock_entry.js:196
|
||||
@@ -39702,7 +39707,7 @@ msgstr "Указанная сумма"
|
||||
#. in DocType 'Supplier'
|
||||
#: erpnext/buying/doctype/supplier/supplier.json
|
||||
msgid "RFQ and Purchase Order Settings"
|
||||
msgstr ""
|
||||
msgstr "Настройки запроса коммерческого предложения и заказа на закупку"
|
||||
|
||||
#: erpnext/buying/doctype/request_for_quotation/request_for_quotation.py:120
|
||||
msgid "RFQs are not allowed for {0} due to a scorecard standing of {1}"
|
||||
@@ -40158,7 +40163,7 @@ msgstr "Потребление сырья"
|
||||
|
||||
#: erpnext/stock/doctype/stock_entry/stock_entry.py:317
|
||||
msgid "Raw Materials Missing"
|
||||
msgstr ""
|
||||
msgstr "Отсутствует сырье"
|
||||
|
||||
#. Label of the raw_materials_received_section (Section Break) field in DocType
|
||||
#. 'Subcontracting Inward Order'
|
||||
@@ -41147,7 +41152,7 @@ msgstr "Удалить номер родительской строки в та
|
||||
|
||||
#: erpnext/setup/doctype/transaction_deletion_record/transaction_deletion_record.js:140
|
||||
msgid "Remove Zero Counts"
|
||||
msgstr ""
|
||||
msgstr "Удалить нулевые значения"
|
||||
|
||||
#: erpnext/stock/doctype/landed_cost_voucher/landed_cost_voucher.js:9
|
||||
msgid "Remove item if charges is not applicable to that item"
|
||||
@@ -43126,7 +43131,7 @@ msgstr "Строка #{0}: Запись в журнале {1} не имеет у
|
||||
|
||||
#: erpnext/assets/doctype/asset_category/asset_category.py:149
|
||||
msgid "Row #{0}: Missing <b>{1}</b> for company <b>{2}</b>."
|
||||
msgstr ""
|
||||
msgstr "Строка #{0}: Отсутствует <b>{1}</b> для компании <b>{2}</b>."
|
||||
|
||||
#: erpnext/assets/doctype/asset/asset.py:678
|
||||
msgid "Row #{0}: Next Depreciation Date cannot be before Available-for-use Date"
|
||||
@@ -43271,7 +43276,10 @@ msgid "Row #{0}: Selling rate for item {1} is lower than its {2}.\n"
|
||||
"\t\t\t\t\tSelling {3} should be atleast {4}.<br><br>Alternatively,\n"
|
||||
"\t\t\t\t\tyou can disable '{5}' in {6} to bypass\n"
|
||||
"\t\t\t\t\tthis validation."
|
||||
msgstr ""
|
||||
msgstr "Строка #{0}: Продажный курс для товара {1} ниже, чем для его {2}.\n"
|
||||
"\t\t\t\t\tПродажный курс для {3} должен быть не ниже {4}.<br><br>В качестве альтернативы,\n"
|
||||
"\t\t\t\t\tвы можете отключить '{5}' в {6}, чтобы обойти\n"
|
||||
"\t\t\t\t\tэту проверку."
|
||||
|
||||
#: erpnext/manufacturing/doctype/work_order/work_order.py:276
|
||||
msgid "Row #{0}: Sequence ID must be {1} or {2} for Operation {3}."
|
||||
@@ -43705,7 +43713,7 @@ msgstr "Строка {0}: Позиция {1} должна быть субпод
|
||||
|
||||
#: erpnext/controllers/subcontracting_controller.py:183
|
||||
msgid "Row {0}: Item {1} must be linked to a {2}."
|
||||
msgstr ""
|
||||
msgstr "Строка {0}: Элемент {1} должен быть связан с {2}."
|
||||
|
||||
#: erpnext/controllers/subcontracting_controller.py:204
|
||||
msgid "Row {0}: Item {1}'s quantity cannot be higher than the available quantity."
|
||||
@@ -45845,7 +45853,7 @@ msgstr "Настройки серии и партии товара"
|
||||
#. Label of the section_break_jcmx (Section Break) field in DocType 'Job Card'
|
||||
#: erpnext/manufacturing/doctype/job_card/job_card.json
|
||||
msgid "Serial / Batch"
|
||||
msgstr ""
|
||||
msgstr "Серийный номер/номер партии"
|
||||
|
||||
#. Label of the serial_and_batch_bundle (Link) field in DocType 'Stock
|
||||
#. Reconciliation Item'
|
||||
@@ -46642,7 +46650,7 @@ msgstr "Установить общую сумму на метод оплаты
|
||||
#. 'Selling Settings'
|
||||
#: erpnext/selling/doctype/selling_settings/selling_settings.json
|
||||
msgid "Set Incoming Rate as Zero for Expired Batch"
|
||||
msgstr ""
|
||||
msgstr "Установить нулевую стоимость входящей партии для просроченных товаров"
|
||||
|
||||
#. Description of the 'Territory Targets' (Section Break) field in DocType
|
||||
#. 'Territory'
|
||||
@@ -47590,7 +47598,7 @@ msgstr "Одновременный"
|
||||
|
||||
#: erpnext/assets/doctype/asset_category/asset_category.py:183
|
||||
msgid "Since there are active depreciable assets under this category, the following accounts are required. <br><br>"
|
||||
msgstr ""
|
||||
msgstr "Поскольку в этой категории имеются активные амортизируемые активы, необходимы следующие счета. <br><br>"
|
||||
|
||||
#: erpnext/stock/doctype/stock_entry/stock_entry.py:688
|
||||
msgid "Since there is a process loss of {0} units for the finished good {1}, you should reduce the quantity by {0} units for the finished good {1} in the Items Table."
|
||||
@@ -47644,7 +47652,7 @@ msgstr "Пропустить передачу материалов на скла
|
||||
|
||||
#: erpnext/setup/doctype/transaction_deletion_record/transaction_deletion_record.py:561
|
||||
msgid "Skipped {0} DocType(s):<br>{1}"
|
||||
msgstr ""
|
||||
msgstr "Пропущено {0} DocType(s):<br>{1}"
|
||||
|
||||
#. Label of the customer_skype (Data) field in DocType 'Appointment'
|
||||
#: erpnext/crm/doctype/appointment/appointment.json
|
||||
@@ -49952,7 +49960,7 @@ msgstr "Время поставки от поставщика (дни)"
|
||||
#. Label of a Workspace Sidebar Item
|
||||
#: erpnext/workspace_sidebar/financial_reports.json
|
||||
msgid "Supplier Ledger"
|
||||
msgstr ""
|
||||
msgstr "Главная книга поставщика"
|
||||
|
||||
#. Name of a report
|
||||
#. Label of a Link in the Financial Reports Workspace
|
||||
@@ -50848,7 +50856,7 @@ msgstr "Настройки налогов"
|
||||
#. Label of a Workspace Sidebar Item
|
||||
#: erpnext/workspace_sidebar/selling.json
|
||||
msgid "Tax Template"
|
||||
msgstr ""
|
||||
msgstr "Шаблон Налога"
|
||||
|
||||
#: erpnext/accounts/doctype/tax_rule/tax_rule.py:83
|
||||
msgid "Tax Template is mandatory."
|
||||
@@ -51682,7 +51690,7 @@ msgstr "Поля от Акционера и Акционера не могут
|
||||
|
||||
#: erpnext/accounts/notification/notification_for_new_fiscal_year/notification_for_new_fiscal_year.html:40
|
||||
msgid "The fiscal year has been automatically created in a Disabled state to maintain consistency with the previous fiscal year's status."
|
||||
msgstr ""
|
||||
msgstr "Для обеспечения согласованности со статусом предыдущего финансового года финансовый год был автоматически создан в состоянии «Отключено»."
|
||||
|
||||
#: erpnext/accounts/doctype/share_transfer/share_transfer.py:240
|
||||
msgid "The folio numbers are not matching"
|
||||
@@ -52562,7 +52570,7 @@ msgstr "Ко времени"
|
||||
|
||||
#: erpnext/setup/doctype/transaction_deletion_record/transaction_deletion_record.js:118
|
||||
msgid "To Delete list generated with {0} DocTypes"
|
||||
msgstr ""
|
||||
msgstr "Список для удаления, создан для {0} типов документов"
|
||||
|
||||
#. Option for the 'Sales Order Status' (Select) field in DocType 'Production
|
||||
#. Plan'
|
||||
@@ -53113,7 +53121,7 @@ msgstr "Всего завершено кол-во"
|
||||
|
||||
#: erpnext/manufacturing/doctype/job_card/job_card.py:189
|
||||
msgid "Total Completed Qty is required for Job Card {0}, please start and complete the job card before submission"
|
||||
msgstr ""
|
||||
msgstr "Для ввода данных в карточку задания {0} необходимо указать общее количество выполненных работ. Пожалуйста, начните и завершите заполнение карточки задания перед проведением"
|
||||
|
||||
#. Label of the total_consumed_material_cost (Currency) field in DocType
|
||||
#. 'Project'
|
||||
@@ -53522,7 +53530,7 @@ msgstr "Совокупный налог"
|
||||
|
||||
#: erpnext/accounts/report/tds_computation_summary/tds_computation_summary.py:109
|
||||
msgid "Total Taxable Amount"
|
||||
msgstr ""
|
||||
msgstr "Общая налогооблагаемая сумма"
|
||||
|
||||
#. Label of the total_taxes_and_charges (Currency) field in DocType 'Payment
|
||||
#. Entry'
|
||||
@@ -53747,7 +53755,7 @@ msgstr "Всего (кол-во)"
|
||||
#: erpnext/selling/doctype/sales_order/sales_order.json
|
||||
#: erpnext/stock/doctype/purchase_receipt/purchase_receipt.json
|
||||
msgid "Totals (Company Currency)"
|
||||
msgstr ""
|
||||
msgstr "Всего (валюта компании)"
|
||||
|
||||
#: erpnext/stock/doctype/item/item_dashboard.py:33
|
||||
msgid "Traceability"
|
||||
@@ -53856,15 +53864,15 @@ msgstr "Элемент записи удаления транзакции"
|
||||
#. Name of a DocType
|
||||
#: erpnext/setup/doctype/transaction_deletion_record_to_delete/transaction_deletion_record_to_delete.json
|
||||
msgid "Transaction Deletion Record To Delete"
|
||||
msgstr ""
|
||||
msgstr "Запись удаления транзакции"
|
||||
|
||||
#: erpnext/setup/doctype/transaction_deletion_record/transaction_deletion_record.py:1098
|
||||
msgid "Transaction Deletion Record {0} is already running. {1}"
|
||||
msgstr ""
|
||||
msgstr "Запись удаления транзакции {0} уже выполняется. {1}"
|
||||
|
||||
#: erpnext/setup/doctype/transaction_deletion_record/transaction_deletion_record.py:1117
|
||||
msgid "Transaction Deletion Record {0} is currently deleting {1}. Cannot save documents until deletion completes."
|
||||
msgstr ""
|
||||
msgstr "Запись удаления транзакции {0} в настоящее время удаляет {1}. Невозможно сохранить документы до завершения процесса."
|
||||
|
||||
#. Label of the transaction_details_section (Section Break) field in DocType
|
||||
#. 'GL Entry'
|
||||
@@ -53900,7 +53908,7 @@ msgstr "Название транзакции"
|
||||
|
||||
#: erpnext/stock/report/negative_batch_report/negative_batch_report.py:60
|
||||
msgid "Transaction Qty"
|
||||
msgstr ""
|
||||
msgstr "Количество транзакций"
|
||||
|
||||
#. Label of the transaction_settings_section (Tab Break) field in DocType
|
||||
#. 'Buying Settings'
|
||||
@@ -53934,7 +53942,7 @@ msgstr "Валюта транзакции: {0} не может отличать
|
||||
|
||||
#: erpnext/assets/doctype/asset_movement/asset_movement.py:65
|
||||
msgid "Transaction date can't be earlier than previous movement date"
|
||||
msgstr ""
|
||||
msgstr "Дата транзакции не может быть раньше предыдущей даты движения"
|
||||
|
||||
#. Description of the 'Applicable For' (Section Break) field in DocType 'Tax
|
||||
#. Withholding Entry'
|
||||
@@ -54500,7 +54508,7 @@ msgstr "URL может быть только строкой"
|
||||
#: erpnext/selling/doctype/sales_order/sales_order.json
|
||||
#: erpnext/stock/doctype/delivery_note/delivery_note.json
|
||||
msgid "UTM Analytics"
|
||||
msgstr ""
|
||||
msgstr "UTM аналитика"
|
||||
|
||||
#. Option for the 'Data Fetch Method' (Select) field in DocType 'Accounts
|
||||
#. Settings'
|
||||
@@ -54519,7 +54527,7 @@ msgstr "Несогласованные распределения"
|
||||
|
||||
#: erpnext/setup/doctype/transaction_deletion_record/transaction_deletion_record.py:464
|
||||
msgid "Unable to fetch DocType details. Please contact system administrator."
|
||||
msgstr ""
|
||||
msgstr "Не удалось получить детали DocType. Пожалуйста, свяжитесь с системным администратором."
|
||||
|
||||
#: erpnext/setup/utils.py:182
|
||||
msgid "Unable to find exchange rate for {0} to {1} for key date {2}. Please create a Currency Exchange record manually"
|
||||
@@ -54608,7 +54616,7 @@ msgstr "В таблице «Рабочие часы» можно добавит
|
||||
|
||||
#: erpnext/setup/doctype/transaction_deletion_record/transaction_deletion_record.py:933
|
||||
msgid "Unexpected Naming Series Pattern"
|
||||
msgstr ""
|
||||
msgstr "Непредвиденный шаблон именования серий"
|
||||
|
||||
#. Option for the 'Fulfilment Status' (Select) field in DocType 'Contract'
|
||||
#: erpnext/crm/doctype/contract/contract.json
|
||||
@@ -55212,7 +55220,7 @@ msgstr "Использовать многоуровневую специфика
|
||||
#. DocType 'Global Defaults'
|
||||
#: erpnext/setup/doctype/global_defaults/global_defaults.json
|
||||
msgid "Use Posting Datetime for Naming Documents"
|
||||
msgstr ""
|
||||
msgstr "Использовать дату и время проведения для именования документов"
|
||||
|
||||
#. Label of the fallback_to_default_price_list (Check) field in DocType
|
||||
#. 'Selling Settings'
|
||||
@@ -55358,7 +55366,7 @@ msgstr "Пользователи могут включить флажок, ес
|
||||
#. 'BOM'
|
||||
#: erpnext/manufacturing/doctype/bom/bom.json
|
||||
msgid "Users can make manufacture entry against Job Cards"
|
||||
msgstr ""
|
||||
msgstr "Пользователи могут вносить производственные записи на основании заказ-нарядов"
|
||||
|
||||
#. Description of the 'Role Allowed to Over Bill ' (Link) field in DocType
|
||||
#. 'Accounts Settings'
|
||||
@@ -56023,7 +56031,7 @@ msgstr "Vimeo"
|
||||
|
||||
#: erpnext/setup/doctype/transaction_deletion_record/transaction_deletion_record.py:214
|
||||
msgid "Virtual DocType"
|
||||
msgstr ""
|
||||
msgstr "Виртуальный DocType"
|
||||
|
||||
#: erpnext/templates/pages/help.html:46
|
||||
msgid "Visit the forums"
|
||||
@@ -56558,7 +56566,7 @@ msgstr "Внимание: Сделка {0} уже существует по За
|
||||
|
||||
#: erpnext/setup/doctype/transaction_deletion_record/transaction_deletion_record.js:75
|
||||
msgid "Warning: This action cannot be undone!"
|
||||
msgstr ""
|
||||
msgstr "Внимание: Это действие нельзя отменить!"
|
||||
|
||||
#: erpnext/accounts/doctype/financial_report_template/financial_report_validation.py:74
|
||||
msgid "Warnings"
|
||||
@@ -56640,7 +56648,7 @@ msgstr "Длина волны в мегаметрах"
|
||||
|
||||
#: erpnext/controllers/accounts_controller.py:190
|
||||
msgid "We can see {0} is made against {1}. If you want {1}'s outstanding to be updated, uncheck the '{2}' checkbox."
|
||||
msgstr ""
|
||||
msgstr "Мы видим, что {0} создано для {1}. Если вы хотите обновить незавершенные операции {1}, снимите флажок '{2}'."
|
||||
|
||||
#: erpnext/www/support/index.html:7
|
||||
msgid "We're here to help!"
|
||||
@@ -56780,7 +56788,7 @@ msgstr "Как я могу вам помочь?"
|
||||
|
||||
#: erpnext/setup/doctype/transaction_deletion_record/transaction_deletion_record.js:82
|
||||
msgid "What will be deleted:"
|
||||
msgstr ""
|
||||
msgstr "Что будет удалено:"
|
||||
|
||||
#. Label of the whatsapp_no (Data) field in DocType 'Lead'
|
||||
#. Label of the whatsapp (Data) field in DocType 'Opportunity'
|
||||
@@ -56816,7 +56824,7 @@ msgstr "Если этот флажок установлен, то к каждо
|
||||
#. in DocType 'Global Defaults'
|
||||
#: erpnext/setup/doctype/global_defaults/global_defaults.json
|
||||
msgid "When checked, the system will use the posting datetime of the document for naming the document instead of the creation datetime of the document."
|
||||
msgstr ""
|
||||
msgstr "Если этот параметр установлен, система будет использовать дату и время публикации документа для его именования вместо даты и времени создания документа."
|
||||
|
||||
#: erpnext/stock/doctype/item/item.js:1079
|
||||
msgid "When creating an Item, entering a value for this field will automatically create an Item Price at the backend."
|
||||
@@ -57430,7 +57438,7 @@ msgstr "Вы можете изменить родительский счет н
|
||||
|
||||
#: erpnext/assets/doctype/asset_category/asset_category.py:186
|
||||
msgid "You can either configure default depreciation accounts in the Company or set the required accounts in the following rows: <br><br>"
|
||||
msgstr ""
|
||||
msgstr "Вы можете либо настроить счета амортизации по умолчанию в разделе «Компания», либо указать необходимые счета в следующих строках: <br><br>"
|
||||
|
||||
#: erpnext/accounts/doctype/journal_entry/journal_entry.py:703
|
||||
msgid "You can not enter current voucher in 'Against Journal Entry' column"
|
||||
@@ -57459,7 +57467,7 @@ msgstr "Вы можете задать его как имя машины или
|
||||
|
||||
#: erpnext/controllers/accounts_controller.py:211
|
||||
msgid "You can use {0} to reconcile against {1} later."
|
||||
msgstr ""
|
||||
msgstr "Вы можете использовать {0} для сверки с {1} позже."
|
||||
|
||||
#: erpnext/manufacturing/doctype/job_card/job_card.py:1315
|
||||
msgid "You can't make any changes to Job Card since Work Order is closed."
|
||||
@@ -57675,7 +57683,7 @@ msgstr "в процентах от количества готовой прод
|
||||
|
||||
#: erpnext/stock/doctype/serial_and_batch_bundle/serial_and_batch_bundle.py:1472
|
||||
msgid "as of {0}"
|
||||
msgstr ""
|
||||
msgstr "по состоянию на {0}"
|
||||
|
||||
#: erpnext/www/book_appointment/index.html:43
|
||||
msgid "at"
|
||||
@@ -58149,7 +58157,7 @@ msgstr "{0} в строке {1}"
|
||||
|
||||
#: erpnext/setup/doctype/transaction_deletion_record/transaction_deletion_record.py:450
|
||||
msgid "{0} is a child table and will be deleted automatically with its parent"
|
||||
msgstr ""
|
||||
msgstr "{0} — это дочерняя таблица, и она будет автоматически удалена вместе со своей родительской таблицей"
|
||||
|
||||
#: erpnext/accounts/doctype/pos_profile/pos_profile.py:95
|
||||
msgid "{0} is a mandatory Accounting Dimension. <br>Please set a value for {0} in Accounting Dimensions section."
|
||||
@@ -58276,7 +58284,7 @@ msgstr "{0} единиц товара {1} нет в наличии ни на о
|
||||
|
||||
#: erpnext/stock/doctype/pick_list/pick_list.py:1009
|
||||
msgid "{0} units of Item {1} is not available in any of the warehouses. Other Pick Lists exist for this item."
|
||||
msgstr ""
|
||||
msgstr "{0} единиц товара {1} нет в наличии ни на одном из складов. Для этого товара существуют другие списки комплектации."
|
||||
|
||||
#: erpnext/stock/doctype/stock_ledger_entry/stock_ledger_entry.py:144
|
||||
msgid "{0} units of {1} are required in {2} with the inventory dimension: {3} on {4} {5} for {6} to complete the transaction."
|
||||
@@ -58524,19 +58532,19 @@ msgstr "{0}, завершите операцию {1} перед операцие
|
||||
|
||||
#: erpnext/setup/doctype/transaction_deletion_record/transaction_deletion_record.py:521
|
||||
msgid "{0}: Child table (auto-deleted with parent)"
|
||||
msgstr ""
|
||||
msgstr "{0}: Дочерняя таблица (автоматически удаляется вместе с родительской)"
|
||||
|
||||
#: erpnext/setup/doctype/transaction_deletion_record/transaction_deletion_record.py:516
|
||||
msgid "{0}: Not found"
|
||||
msgstr ""
|
||||
msgstr "{0} Не найдено"
|
||||
|
||||
#: erpnext/setup/doctype/transaction_deletion_record/transaction_deletion_record.py:512
|
||||
msgid "{0}: Protected DocType"
|
||||
msgstr ""
|
||||
msgstr "{0}: Защищенный DocType"
|
||||
|
||||
#: erpnext/setup/doctype/transaction_deletion_record/transaction_deletion_record.py:526
|
||||
msgid "{0}: Virtual DocType (no database table)"
|
||||
msgstr ""
|
||||
msgstr "{0}: Виртуальный DocType (нет таблицы в базе данных)"
|
||||
|
||||
#: erpnext/controllers/accounts_controller.py:539
|
||||
msgid "{0}: {1} does not belong to the Company: {2}"
|
||||
|
||||
@@ -3,7 +3,7 @@ msgstr ""
|
||||
"Project-Id-Version: frappe\n"
|
||||
"Report-Msgid-Bugs-To: hello@frappe.io\n"
|
||||
"POT-Creation-Date: 2026-02-22 09:43+0000\n"
|
||||
"PO-Revision-Date: 2026-02-22 16:38\n"
|
||||
"PO-Revision-Date: 2026-02-27 16:51\n"
|
||||
"Last-Translator: hello@frappe.io\n"
|
||||
"Language-Team: Serbian (Cyrillic)\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
@@ -25,7 +25,12 @@ msgid "\n"
|
||||
"\t\t\tIf it is not possible to make an adjustment entry, please enable 'Allow Negative Stock for Batch' in Stock Settings to proceed.\n"
|
||||
"\t\t\tHowever, enabling this setting may lead to negative stock in the system.\n"
|
||||
"\t\t\tSo please ensure the stock levels are adjusted as soon as possible to maintain the correct valuation rate."
|
||||
msgstr ""
|
||||
msgstr "\n"
|
||||
"\t\t\tШаржа {0} ставке {1} има негативно стање залиха у складишту {2}{3}.\n"
|
||||
"\t\t\tМолимо Вас да унесете количину залиха од {4} како бисте наставили са овим уносом.\n"
|
||||
"\t\t\tУколико није могуће извршити корективно књижење, омогућите опцију 'Дозволи негативно стање залиха за шаржу' у подешавањима залиха како бисте наставили.\n"
|
||||
"\t\t\tМеђутим, омогућавањем ове опције може довести до негативног стања залиха у систему.\n"
|
||||
"\t\t\tОбавезно ускладите стање залиха што је пре могуће како би стопа вредновања остала тачна."
|
||||
|
||||
#. Label of the column_break_32 (Column Break) field in DocType 'Email Digest'
|
||||
#: erpnext/setup/doctype/email_digest/email_digest.json
|
||||
@@ -1094,7 +1099,7 @@ msgstr "Нови састанак је заказан за Вас са {0}"
|
||||
|
||||
#: erpnext/accounts/notification/notification_for_new_fiscal_year/notification_for_new_fiscal_year.html:3
|
||||
msgid "A new fiscal year has been automatically created."
|
||||
msgstr ""
|
||||
msgstr "Нова фискална година је аутоматски креирана."
|
||||
|
||||
#: erpnext/accounts/doctype/sales_taxes_and_charges_template/sales_taxes_and_charges_template.py:96
|
||||
msgid "A template with tax category {0} already exists. Only one template is allowed with each tax category"
|
||||
@@ -1149,7 +1154,7 @@ msgstr "Датум истека годишњег уговора о одржав
|
||||
#. Label of a Workspace Sidebar Item
|
||||
#: erpnext/workspace_sidebar/financial_reports.json
|
||||
msgid "AP Summary"
|
||||
msgstr ""
|
||||
msgstr "Резиме обавеза"
|
||||
|
||||
#. Label of the api_details_section (Section Break) field in DocType 'Currency
|
||||
#. Exchange Settings'
|
||||
@@ -1160,7 +1165,7 @@ msgstr "API Детаљи"
|
||||
#. Label of a Workspace Sidebar Item
|
||||
#: erpnext/workspace_sidebar/financial_reports.json
|
||||
msgid "AR Summary"
|
||||
msgstr ""
|
||||
msgstr "Резиме потраживања"
|
||||
|
||||
#. Label of the awb_number (Data) field in DocType 'Shipment'
|
||||
#: erpnext/stock/doctype/shipment/shipment.json
|
||||
@@ -2132,7 +2137,7 @@ msgstr "Подешавање рачуна"
|
||||
#: erpnext/desktop_icon/accounts_setup.json
|
||||
#: erpnext/workspace_sidebar/accounts_setup.json
|
||||
msgid "Accounts Setup"
|
||||
msgstr ""
|
||||
msgstr "Подешавање рачуна"
|
||||
|
||||
#: erpnext/accounts/doctype/journal_entry/journal_entry.py:1319
|
||||
msgid "Accounts table cannot be blank."
|
||||
@@ -7265,7 +7270,7 @@ msgstr "Рачун за прекорачење"
|
||||
#. Label of a Workspace Sidebar Item
|
||||
#: erpnext/workspace_sidebar/banking.json
|
||||
msgid "Bank Reconciliation"
|
||||
msgstr ""
|
||||
msgstr "Банкарско усклађивање"
|
||||
|
||||
#. Name of a report
|
||||
#. Label of a Link in the Invoicing Workspace
|
||||
@@ -8459,7 +8464,7 @@ msgstr "Датум почетка буџета"
|
||||
#. Label of a Workspace Sidebar Item
|
||||
#: erpnext/workspace_sidebar/budget.json
|
||||
msgid "Budget Variance"
|
||||
msgstr ""
|
||||
msgstr "Одступање од буџета"
|
||||
|
||||
#. Name of a report
|
||||
#. Label of a Link in the Invoicing Workspace
|
||||
@@ -8653,7 +8658,7 @@ msgstr "CC за"
|
||||
#. Label of a Workspace Sidebar Item
|
||||
#: erpnext/workspace_sidebar/accounts_setup.json
|
||||
msgid "COA Importer"
|
||||
msgstr ""
|
||||
msgstr "Увоз контног оквира"
|
||||
|
||||
#. Option for the 'Barcode Type' (Select) field in DocType 'Item Barcode'
|
||||
#: erpnext/stock/doctype/item_barcode/item_barcode.json
|
||||
@@ -9287,7 +9292,7 @@ msgstr "Не може се поставити више подразумеван
|
||||
|
||||
#: erpnext/assets/doctype/asset_category/asset_category.py:108
|
||||
msgid "Cannot set multiple account rows for the same company"
|
||||
msgstr ""
|
||||
msgstr "Није могуће поставити више редова рачуна за исту компанију"
|
||||
|
||||
#: erpnext/controllers/accounts_controller.py:3885
|
||||
msgid "Cannot set quantity less than delivered quantity"
|
||||
@@ -11361,7 +11366,7 @@ msgstr "Консолидовани финансијски извештај"
|
||||
#. Label of a Workspace Sidebar Item
|
||||
#: erpnext/workspace_sidebar/financial_reports.json
|
||||
msgid "Consolidated Report"
|
||||
msgstr ""
|
||||
msgstr "Консолидован извештај"
|
||||
|
||||
#. Label of the consolidated_invoice (Link) field in DocType 'POS Invoice'
|
||||
#. Label of the consolidated_invoice (Link) field in DocType 'POS Invoice Merge
|
||||
@@ -13717,7 +13722,7 @@ msgstr "Купац локална наруџбина бр."
|
||||
#. Label of a Workspace Sidebar Item
|
||||
#: erpnext/workspace_sidebar/financial_reports.json
|
||||
msgid "Customer Ledger"
|
||||
msgstr ""
|
||||
msgstr "Књига купаца"
|
||||
|
||||
#. Name of a report
|
||||
#. Label of a Link in the Financial Reports Workspace
|
||||
@@ -14472,7 +14477,7 @@ msgstr "Подаци о ентитету где се врши одбитак"
|
||||
#. Label of a Workspace Sidebar Item
|
||||
#: erpnext/workspace_sidebar/taxes.json
|
||||
msgid "Deduction Certificate"
|
||||
msgstr ""
|
||||
msgstr "Потврда о одбитку"
|
||||
|
||||
#. Label of the deductions_or_loss_section (Section Break) field in DocType
|
||||
#. 'Payment Entry'
|
||||
@@ -16636,7 +16641,7 @@ msgstr "Број докумената"
|
||||
|
||||
#: erpnext/stock/report/negative_batch_report/negative_batch_report.py:78
|
||||
msgid "Document No"
|
||||
msgstr ""
|
||||
msgstr "Број документа"
|
||||
|
||||
#. Label of the document_type (Link) field in DocType 'Subscription Invoice'
|
||||
#: erpnext/accounts/doctype/subscription_invoice/subscription_invoice.json
|
||||
@@ -18654,7 +18659,7 @@ msgstr "ФИФО/ЛИФО ред чекања"
|
||||
#. Label of a Workspace Sidebar Item
|
||||
#: erpnext/workspace_sidebar/accounts_setup.json
|
||||
msgid "FX Revaluation"
|
||||
msgstr ""
|
||||
msgstr "Ревалоризација девизног курса"
|
||||
|
||||
#. Name of a UOM
|
||||
#: erpnext/setup/setup_wizard/data/uom_data.json
|
||||
@@ -18749,7 +18754,7 @@ msgstr "Повратна информација од"
|
||||
#. Label of a Workspace Sidebar Item
|
||||
#: erpnext/workspace_sidebar/quality.json
|
||||
msgid "Feedback Template"
|
||||
msgstr ""
|
||||
msgstr "Шаблон за повратне информације"
|
||||
|
||||
#. Option for the 'Reference Type' (Select) field in DocType 'Journal Entry
|
||||
#. Account'
|
||||
@@ -19322,7 +19327,7 @@ msgstr "Фискална година компаније"
|
||||
|
||||
#: erpnext/accounts/notification/notification_for_new_fiscal_year/notification_for_new_fiscal_year.html:5
|
||||
msgid "Fiscal Year Details"
|
||||
msgstr ""
|
||||
msgstr "Детаљи фискалне године"
|
||||
|
||||
#: erpnext/accounts/doctype/fiscal_year/fiscal_year.py:47
|
||||
msgid "Fiscal Year End Date should be one year after Fiscal Year Start Date"
|
||||
@@ -21898,7 +21903,7 @@ msgstr "Уколико је омогућено, изворно и циљно с
|
||||
#. 'Stock Settings'
|
||||
#: erpnext/stock/doctype/stock_settings/stock_settings.json
|
||||
msgid "If enabled, the system will allow negative stock entries for the batch. But, this may lead to incorrect valuation rates, so it is recommended to avoid using this option. The system will permit negative stock only when it is caused by backdated entries and will validate and block negative stock in all other cases."
|
||||
msgstr ""
|
||||
msgstr "Уколико је омогућено, систем ће дозволити књижење негативног стања залиха за шаржу. То може довести до нетачне стопе вредновања, па се препоручује избегавање ове опције. Систем ће дозволити негативно стање само у случају ретроактивних књижења и блокираће негативно стање у свим осталим случајевима."
|
||||
|
||||
#. Description of the 'Allow UOM with Conversion Rate Defined in Item' (Check)
|
||||
#. field in DocType 'Stock Settings'
|
||||
@@ -23920,7 +23925,7 @@ msgstr "Улазно"
|
||||
#. Label of a Workspace Sidebar Item
|
||||
#: erpnext/workspace_sidebar/subcontracting.json
|
||||
msgid "Inward Order"
|
||||
msgstr ""
|
||||
msgstr "Налог за пријем"
|
||||
|
||||
#. Label of the is_account_payable (Check) field in DocType 'Cheque Print
|
||||
#. Template'
|
||||
@@ -26001,7 +26006,7 @@ msgstr "Регистар продаје по ставкама"
|
||||
#. Label of a Workspace Sidebar Item
|
||||
#: erpnext/workspace_sidebar/financial_reports.json
|
||||
msgid "Item-wise sales Register"
|
||||
msgstr ""
|
||||
msgstr "Књига продаје по ставкама"
|
||||
|
||||
#: erpnext/stock/get_item_details.py:713
|
||||
msgid "Item/Item Code required to get Item Tax Template."
|
||||
@@ -26035,7 +26040,7 @@ msgstr "Потребне ставке"
|
||||
#. Label of a Workspace Sidebar Item
|
||||
#: erpnext/workspace_sidebar/subcontracting.json
|
||||
msgid "Items To Be Received"
|
||||
msgstr ""
|
||||
msgstr "Ставке за пријем"
|
||||
|
||||
#. Label of a Link in the Buying Workspace
|
||||
#. Name of a report
|
||||
@@ -28327,7 +28332,7 @@ msgstr "Издавање материјала"
|
||||
#. Label of a Workspace Sidebar Item
|
||||
#: erpnext/workspace_sidebar/manufacturing.json
|
||||
msgid "Material Planning"
|
||||
msgstr ""
|
||||
msgstr "Планирање материјала"
|
||||
|
||||
#. Option for the 'Purpose' (Select) field in DocType 'Stock Entry'
|
||||
#. Option for the 'Purpose' (Select) field in DocType 'Stock Entry Type'
|
||||
@@ -28605,7 +28610,7 @@ msgstr "Материјал ка добављачу"
|
||||
#. Label of a Workspace Sidebar Item
|
||||
#: erpnext/workspace_sidebar/subcontracting.json
|
||||
msgid "Materials To Be Transferred"
|
||||
msgstr ""
|
||||
msgstr "Материјал за пренос"
|
||||
|
||||
#: erpnext/controllers/subcontracting_controller.py:1569
|
||||
msgid "Materials are already received against the {0} {1}"
|
||||
@@ -28851,7 +28856,7 @@ msgstr "Поруке дуже од 160 карактера биће подеље
|
||||
|
||||
#: erpnext/setup/install.py:127
|
||||
msgid "Messaging CRM Campaign"
|
||||
msgstr ""
|
||||
msgstr "CRM кампања за поруке"
|
||||
|
||||
#. Name of a UOM
|
||||
#: erpnext/setup/setup_wizard/data/uom_data.json
|
||||
@@ -29148,7 +29153,7 @@ msgstr "Недостајући рачун"
|
||||
|
||||
#: erpnext/assets/doctype/asset_category/asset_category.py:191
|
||||
msgid "Missing Accounts"
|
||||
msgstr ""
|
||||
msgstr "Недостајући рачуни"
|
||||
|
||||
#: erpnext/accounts/doctype/sales_invoice/sales_invoice.py:430
|
||||
msgid "Missing Asset"
|
||||
@@ -29193,7 +29198,7 @@ msgstr "Недостаје број серије пакета"
|
||||
|
||||
#: erpnext/assets/doctype/asset_category/asset_category.py:156
|
||||
msgid "Missing account configuration for company <b>{0}</b>."
|
||||
msgstr ""
|
||||
msgstr "Недостаје конфигурација рачун за компанију <b>{0}</b>."
|
||||
|
||||
#: erpnext/stock/doctype/delivery_trip/delivery_trip.js:154
|
||||
msgid "Missing email template for dispatch. Please set one in Delivery Settings."
|
||||
@@ -29613,7 +29618,7 @@ msgstr "Анализа потребна"
|
||||
#. Name of a report
|
||||
#: erpnext/stock/report/negative_batch_report/negative_batch_report.json
|
||||
msgid "Negative Batch Report"
|
||||
msgstr ""
|
||||
msgstr "Извештај о шаржама са негативним стањем"
|
||||
|
||||
#: erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.py:622
|
||||
msgid "Negative Quantity is not allowed"
|
||||
@@ -30015,7 +30020,7 @@ msgstr "Нови расходи"
|
||||
|
||||
#: erpnext/accounts/notification/notification_for_new_fiscal_year/notification_for_new_fiscal_year.html:1
|
||||
msgid "New Fiscal Year - {0}"
|
||||
msgstr ""
|
||||
msgstr "Нова фискална година - {0}"
|
||||
|
||||
#. Label of the income (Check) field in DocType 'Email Digest'
|
||||
#: erpnext/setup/doctype/email_digest/email_digest.json
|
||||
@@ -31440,7 +31445,7 @@ msgstr "Ставка почетне фактуре"
|
||||
#. Label of a Workspace Sidebar Item
|
||||
#: erpnext/workspace_sidebar/accounts_setup.json
|
||||
msgid "Opening Invoice Tool"
|
||||
msgstr ""
|
||||
msgstr "Алат за унос почетних фактура"
|
||||
|
||||
#: erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py:1646
|
||||
#: erpnext/accounts/doctype/sales_invoice/sales_invoice.py:1990
|
||||
@@ -32211,7 +32216,7 @@ msgstr "Излазно"
|
||||
#. Label of a Workspace Sidebar Item
|
||||
#: erpnext/workspace_sidebar/subcontracting.json
|
||||
msgid "Outward Order"
|
||||
msgstr ""
|
||||
msgstr "Налог за издавање"
|
||||
|
||||
#. Label of the over_billing_allowance (Currency) field in DocType 'Accounts
|
||||
#. Settings'
|
||||
@@ -33926,7 +33931,7 @@ msgstr "Плаћање примљено"
|
||||
#. Label of a Workspace Sidebar Item
|
||||
#: erpnext/workspace_sidebar/payments.json
|
||||
msgid "Payment Reconciliaition"
|
||||
msgstr ""
|
||||
msgstr "Усклађивање плаћања"
|
||||
|
||||
#. Name of a DocType
|
||||
#. Label of the payment_reconciliation (Table) field in DocType 'POS Closing
|
||||
@@ -35489,7 +35494,7 @@ msgstr "Молимо Вас да освежите или ресетујете Pl
|
||||
|
||||
#: erpnext/accounts/notification/notification_for_new_fiscal_year/notification_for_new_fiscal_year.html:43
|
||||
msgid "Please review the {0} configuration and complete any required financial setup activities."
|
||||
msgstr ""
|
||||
msgstr "Погледајте конфигурацију {0} и довршите неопходна финансијска подешавања."
|
||||
|
||||
#: erpnext/accounts/doctype/process_statement_of_accounts/process_statement_of_accounts.js:12
|
||||
#: erpnext/accounts/doctype/process_statement_of_accounts/process_statement_of_accounts.js:28
|
||||
@@ -36578,7 +36583,7 @@ msgstr "Претходна фискална година није затворе
|
||||
|
||||
#: erpnext/stock/report/negative_batch_report/negative_batch_report.py:54
|
||||
msgid "Previous Qty"
|
||||
msgstr ""
|
||||
msgstr "Претходна количина"
|
||||
|
||||
#. Label of the previous_work_experience (Section Break) field in DocType
|
||||
#. 'Employee'
|
||||
@@ -40652,7 +40657,7 @@ msgstr "Величина реда за усклађивање"
|
||||
#. Label of a Workspace Sidebar Item
|
||||
#: erpnext/workspace_sidebar/banking.json
|
||||
msgid "Reconciliation Statement"
|
||||
msgstr ""
|
||||
msgstr "Извештај о усклађености"
|
||||
|
||||
#. Label of the reconciliation_takes_effect_on (Select) field in DocType
|
||||
#. 'Company'
|
||||
@@ -40941,7 +40946,7 @@ msgstr "Регионални"
|
||||
#. Label of a Workspace Sidebar Item
|
||||
#: erpnext/workspace_sidebar/financial_reports.json
|
||||
msgid "Registers"
|
||||
msgstr ""
|
||||
msgstr "Регистри"
|
||||
|
||||
#. Label of the registration_details (Code) field in DocType 'Company'
|
||||
#: erpnext/setup/doctype/company/company.json
|
||||
@@ -43127,7 +43132,7 @@ msgstr "Ред #{0}: Налог књижења {1} не садржи рачун
|
||||
|
||||
#: erpnext/assets/doctype/asset_category/asset_category.py:149
|
||||
msgid "Row #{0}: Missing <b>{1}</b> for company <b>{2}</b>."
|
||||
msgstr ""
|
||||
msgstr "Ред #{0}: Недостаје <b>{1}</b> за компанију <b>{2}</b>."
|
||||
|
||||
#: erpnext/assets/doctype/asset/asset.py:678
|
||||
msgid "Row #{0}: Next Depreciation Date cannot be before Available-for-use Date"
|
||||
@@ -47596,7 +47601,7 @@ msgstr "Симултано"
|
||||
|
||||
#: erpnext/assets/doctype/asset_category/asset_category.py:183
|
||||
msgid "Since there are active depreciable assets under this category, the following accounts are required. <br><br>"
|
||||
msgstr ""
|
||||
msgstr "Пошто постоје активна средства која се амортизују у овој категорији, следећи рачуни су обавезни. <br><br>"
|
||||
|
||||
#: erpnext/stock/doctype/stock_entry/stock_entry.py:688
|
||||
msgid "Since there is a process loss of {0} units for the finished good {1}, you should reduce the quantity by {0} units for the finished good {1} in the Items Table."
|
||||
@@ -49958,7 +49963,7 @@ msgstr "Време испоруке добављача (дани)"
|
||||
#. Label of a Workspace Sidebar Item
|
||||
#: erpnext/workspace_sidebar/financial_reports.json
|
||||
msgid "Supplier Ledger"
|
||||
msgstr ""
|
||||
msgstr "Књига добављача"
|
||||
|
||||
#. Name of a report
|
||||
#. Label of a Link in the Financial Reports Workspace
|
||||
@@ -50854,7 +50859,7 @@ msgstr "Подешавање пореза"
|
||||
#. Label of a Workspace Sidebar Item
|
||||
#: erpnext/workspace_sidebar/selling.json
|
||||
msgid "Tax Template"
|
||||
msgstr ""
|
||||
msgstr "Порески шаблон"
|
||||
|
||||
#: erpnext/accounts/doctype/tax_rule/tax_rule.py:83
|
||||
msgid "Tax Template is mandatory."
|
||||
@@ -51689,7 +51694,7 @@ msgstr "Поља од власника и ка власнику не могу б
|
||||
|
||||
#: erpnext/accounts/notification/notification_for_new_fiscal_year/notification_for_new_fiscal_year.html:40
|
||||
msgid "The fiscal year has been automatically created in a Disabled state to maintain consistency with the previous fiscal year's status."
|
||||
msgstr ""
|
||||
msgstr "Фискална година је аутоматски креирана у онемогућеном статусу ради усклађености са статусом претходне фискалне године."
|
||||
|
||||
#: erpnext/accounts/doctype/share_transfer/share_transfer.py:240
|
||||
msgid "The folio numbers are not matching"
|
||||
@@ -53907,7 +53912,7 @@ msgstr "Назив трансакције"
|
||||
|
||||
#: erpnext/stock/report/negative_batch_report/negative_batch_report.py:60
|
||||
msgid "Transaction Qty"
|
||||
msgstr ""
|
||||
msgstr "Трансакциона количина"
|
||||
|
||||
#. Label of the transaction_settings_section (Tab Break) field in DocType
|
||||
#. 'Buying Settings'
|
||||
@@ -57437,7 +57442,7 @@ msgstr "Можете променити матични рачун у рачун
|
||||
|
||||
#: erpnext/assets/doctype/asset_category/asset_category.py:186
|
||||
msgid "You can either configure default depreciation accounts in the Company or set the required accounts in the following rows: <br><br>"
|
||||
msgstr ""
|
||||
msgstr "Можете конфигурисати подразумеване рачуне амортизације у подешавањима компаније или унети потребне рачуне у следећим редовима: <br><br>"
|
||||
|
||||
#: erpnext/accounts/doctype/journal_entry/journal_entry.py:703
|
||||
msgid "You can not enter current voucher in 'Against Journal Entry' column"
|
||||
@@ -57682,7 +57687,7 @@ msgstr "као проценат количине финалне ставке"
|
||||
|
||||
#: erpnext/stock/doctype/serial_and_batch_bundle/serial_and_batch_bundle.py:1472
|
||||
msgid "as of {0}"
|
||||
msgstr ""
|
||||
msgstr "на дан {0}"
|
||||
|
||||
#: erpnext/www/book_appointment/index.html:43
|
||||
msgid "at"
|
||||
@@ -58283,7 +58288,7 @@ msgstr "{0} јединица ставке {1} није доступно ни у
|
||||
|
||||
#: erpnext/stock/doctype/pick_list/pick_list.py:1009
|
||||
msgid "{0} units of Item {1} is not available in any of the warehouses. Other Pick Lists exist for this item."
|
||||
msgstr ""
|
||||
msgstr "{0} јединица ставке {1} није доступно ни у једном складишту. Постоје друге листе за одабир за ову ставку."
|
||||
|
||||
#: erpnext/stock/doctype/stock_ledger_entry/stock_ledger_entry.py:144
|
||||
msgid "{0} units of {1} are required in {2} with the inventory dimension: {3} on {4} {5} for {6} to complete the transaction."
|
||||
|
||||
@@ -3,7 +3,7 @@ msgstr ""
|
||||
"Project-Id-Version: frappe\n"
|
||||
"Report-Msgid-Bugs-To: hello@frappe.io\n"
|
||||
"POT-Creation-Date: 2026-02-22 09:43+0000\n"
|
||||
"PO-Revision-Date: 2026-02-22 16:38\n"
|
||||
"PO-Revision-Date: 2026-02-27 16:51\n"
|
||||
"Last-Translator: hello@frappe.io\n"
|
||||
"Language-Team: Serbian (Latin)\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
@@ -25,7 +25,12 @@ msgid "\n"
|
||||
"\t\t\tIf it is not possible to make an adjustment entry, please enable 'Allow Negative Stock for Batch' in Stock Settings to proceed.\n"
|
||||
"\t\t\tHowever, enabling this setting may lead to negative stock in the system.\n"
|
||||
"\t\t\tSo please ensure the stock levels are adjusted as soon as possible to maintain the correct valuation rate."
|
||||
msgstr ""
|
||||
msgstr "\n"
|
||||
"\t\t\tŠarža {0} stavke {1} ima negativno stanje zaliha u skladištu {2}{3}.\n"
|
||||
"\t\t\tMolimo Vas da uneste količinu zaliha od {4} kako biste nastavili sa ovim unosom.\n"
|
||||
"\t\t\tUkoliko nije moguće izvršiti korektivno knjiženje, omogućite opciju 'Dozvoli negativno stanje zaliha za šaržu' u podešavanjima zaliha kako biste nastavili.\n"
|
||||
"\t\t\tMeđutim, omogućavanjem ove opcije može dovesti do negativnog stanja zaliha u sistemu.\n"
|
||||
"\t\t\tObavezno uskladite stanje zaliha što je pre moguće kako bi stopa vrednovanja ostala tačna."
|
||||
|
||||
#. Label of the column_break_32 (Column Break) field in DocType 'Email Digest'
|
||||
#: erpnext/setup/doctype/email_digest/email_digest.json
|
||||
@@ -1094,7 +1099,7 @@ msgstr "Novi sastanak je zakazan za Vas sa {0}"
|
||||
|
||||
#: erpnext/accounts/notification/notification_for_new_fiscal_year/notification_for_new_fiscal_year.html:3
|
||||
msgid "A new fiscal year has been automatically created."
|
||||
msgstr ""
|
||||
msgstr "Nova fiskalna godina je automatski kreirana."
|
||||
|
||||
#: erpnext/accounts/doctype/sales_taxes_and_charges_template/sales_taxes_and_charges_template.py:96
|
||||
msgid "A template with tax category {0} already exists. Only one template is allowed with each tax category"
|
||||
@@ -1149,7 +1154,7 @@ msgstr "Datum isteka godišnjeg ugovora o održavanju"
|
||||
#. Label of a Workspace Sidebar Item
|
||||
#: erpnext/workspace_sidebar/financial_reports.json
|
||||
msgid "AP Summary"
|
||||
msgstr ""
|
||||
msgstr "Rezime obaveza"
|
||||
|
||||
#. Label of the api_details_section (Section Break) field in DocType 'Currency
|
||||
#. Exchange Settings'
|
||||
@@ -1160,7 +1165,7 @@ msgstr "API Detalji"
|
||||
#. Label of a Workspace Sidebar Item
|
||||
#: erpnext/workspace_sidebar/financial_reports.json
|
||||
msgid "AR Summary"
|
||||
msgstr ""
|
||||
msgstr "Rezime potraživanja"
|
||||
|
||||
#. Label of the awb_number (Data) field in DocType 'Shipment'
|
||||
#: erpnext/stock/doctype/shipment/shipment.json
|
||||
@@ -2132,7 +2137,7 @@ msgstr "Podešavanje računa"
|
||||
#: erpnext/desktop_icon/accounts_setup.json
|
||||
#: erpnext/workspace_sidebar/accounts_setup.json
|
||||
msgid "Accounts Setup"
|
||||
msgstr ""
|
||||
msgstr "Podešavanje računa"
|
||||
|
||||
#: erpnext/accounts/doctype/journal_entry/journal_entry.py:1319
|
||||
msgid "Accounts table cannot be blank."
|
||||
@@ -7265,7 +7270,7 @@ msgstr "Račun za prekoračenje"
|
||||
#. Label of a Workspace Sidebar Item
|
||||
#: erpnext/workspace_sidebar/banking.json
|
||||
msgid "Bank Reconciliation"
|
||||
msgstr ""
|
||||
msgstr "Bankarsko usklađivanje"
|
||||
|
||||
#. Name of a report
|
||||
#. Label of a Link in the Invoicing Workspace
|
||||
@@ -8459,7 +8464,7 @@ msgstr "Datum početka budžeta"
|
||||
#. Label of a Workspace Sidebar Item
|
||||
#: erpnext/workspace_sidebar/budget.json
|
||||
msgid "Budget Variance"
|
||||
msgstr ""
|
||||
msgstr "Odstupanje od budžeta"
|
||||
|
||||
#. Name of a report
|
||||
#. Label of a Link in the Invoicing Workspace
|
||||
@@ -8653,7 +8658,7 @@ msgstr "CC za"
|
||||
#. Label of a Workspace Sidebar Item
|
||||
#: erpnext/workspace_sidebar/accounts_setup.json
|
||||
msgid "COA Importer"
|
||||
msgstr ""
|
||||
msgstr "Uvoz kontnog okvira"
|
||||
|
||||
#. Option for the 'Barcode Type' (Select) field in DocType 'Item Barcode'
|
||||
#: erpnext/stock/doctype/item_barcode/item_barcode.json
|
||||
@@ -9287,7 +9292,7 @@ msgstr "Ne može se postaviti više podrazumevanih stavki za jednu kompaniju."
|
||||
|
||||
#: erpnext/assets/doctype/asset_category/asset_category.py:108
|
||||
msgid "Cannot set multiple account rows for the same company"
|
||||
msgstr ""
|
||||
msgstr "Nije moguće postaviti više redova računa za istu kompaniju"
|
||||
|
||||
#: erpnext/controllers/accounts_controller.py:3885
|
||||
msgid "Cannot set quantity less than delivered quantity"
|
||||
@@ -11361,7 +11366,7 @@ msgstr "Konsolidovani finansijski izveštaj"
|
||||
#. Label of a Workspace Sidebar Item
|
||||
#: erpnext/workspace_sidebar/financial_reports.json
|
||||
msgid "Consolidated Report"
|
||||
msgstr ""
|
||||
msgstr "Konsolidovan izveštaj"
|
||||
|
||||
#. Label of the consolidated_invoice (Link) field in DocType 'POS Invoice'
|
||||
#. Label of the consolidated_invoice (Link) field in DocType 'POS Invoice Merge
|
||||
@@ -13717,7 +13722,7 @@ msgstr "Kupac lokalna narudžbina br."
|
||||
#. Label of a Workspace Sidebar Item
|
||||
#: erpnext/workspace_sidebar/financial_reports.json
|
||||
msgid "Customer Ledger"
|
||||
msgstr ""
|
||||
msgstr "Knjiga kupaca"
|
||||
|
||||
#. Name of a report
|
||||
#. Label of a Link in the Financial Reports Workspace
|
||||
@@ -14472,7 +14477,7 @@ msgstr "Podaci o entitetu gde se vrši odbitak"
|
||||
#. Label of a Workspace Sidebar Item
|
||||
#: erpnext/workspace_sidebar/taxes.json
|
||||
msgid "Deduction Certificate"
|
||||
msgstr ""
|
||||
msgstr "Potvrda o odbitku"
|
||||
|
||||
#. Label of the deductions_or_loss_section (Section Break) field in DocType
|
||||
#. 'Payment Entry'
|
||||
@@ -16636,7 +16641,7 @@ msgstr "Broj dokumenata"
|
||||
|
||||
#: erpnext/stock/report/negative_batch_report/negative_batch_report.py:78
|
||||
msgid "Document No"
|
||||
msgstr ""
|
||||
msgstr "Broj dokumenta"
|
||||
|
||||
#. Label of the document_type (Link) field in DocType 'Subscription Invoice'
|
||||
#: erpnext/accounts/doctype/subscription_invoice/subscription_invoice.json
|
||||
@@ -18654,7 +18659,7 @@ msgstr "FIFO/LIFO red čekanja"
|
||||
#. Label of a Workspace Sidebar Item
|
||||
#: erpnext/workspace_sidebar/accounts_setup.json
|
||||
msgid "FX Revaluation"
|
||||
msgstr ""
|
||||
msgstr "Revalorizacija deviznog kursa"
|
||||
|
||||
#. Name of a UOM
|
||||
#: erpnext/setup/setup_wizard/data/uom_data.json
|
||||
@@ -18749,7 +18754,7 @@ msgstr "Povratna informacija od"
|
||||
#. Label of a Workspace Sidebar Item
|
||||
#: erpnext/workspace_sidebar/quality.json
|
||||
msgid "Feedback Template"
|
||||
msgstr ""
|
||||
msgstr "Šablon za povratne informacije"
|
||||
|
||||
#. Option for the 'Reference Type' (Select) field in DocType 'Journal Entry
|
||||
#. Account'
|
||||
@@ -19322,7 +19327,7 @@ msgstr "Fiskalna godina kompanije"
|
||||
|
||||
#: erpnext/accounts/notification/notification_for_new_fiscal_year/notification_for_new_fiscal_year.html:5
|
||||
msgid "Fiscal Year Details"
|
||||
msgstr ""
|
||||
msgstr "Detalji fiskalne godine"
|
||||
|
||||
#: erpnext/accounts/doctype/fiscal_year/fiscal_year.py:47
|
||||
msgid "Fiscal Year End Date should be one year after Fiscal Year Start Date"
|
||||
@@ -21898,7 +21903,7 @@ msgstr "Ukoliko je omogućeno, izvorno i ciljno skladište u unosu zaliha prenos
|
||||
#. 'Stock Settings'
|
||||
#: erpnext/stock/doctype/stock_settings/stock_settings.json
|
||||
msgid "If enabled, the system will allow negative stock entries for the batch. But, this may lead to incorrect valuation rates, so it is recommended to avoid using this option. The system will permit negative stock only when it is caused by backdated entries and will validate and block negative stock in all other cases."
|
||||
msgstr ""
|
||||
msgstr "Ukoliko je omogućeno, sistem će dozvoliti knjiženje negativnog stanja zaliha za šaržu. To može dovesti do netačne stope vrednovanja, pa se preporučuje izbegavanje ove opcije. Sistem će dozvoliti negativno stanje samo u slučaju retroaktivnih knjiženja i blokiraće negativno stanje u svim ostalim slučajevima."
|
||||
|
||||
#. Description of the 'Allow UOM with Conversion Rate Defined in Item' (Check)
|
||||
#. field in DocType 'Stock Settings'
|
||||
@@ -23920,7 +23925,7 @@ msgstr "Ulazno"
|
||||
#. Label of a Workspace Sidebar Item
|
||||
#: erpnext/workspace_sidebar/subcontracting.json
|
||||
msgid "Inward Order"
|
||||
msgstr ""
|
||||
msgstr "Nalog za prijem"
|
||||
|
||||
#. Label of the is_account_payable (Check) field in DocType 'Cheque Print
|
||||
#. Template'
|
||||
@@ -26001,7 +26006,7 @@ msgstr "Registar prodaje po stavkama"
|
||||
#. Label of a Workspace Sidebar Item
|
||||
#: erpnext/workspace_sidebar/financial_reports.json
|
||||
msgid "Item-wise sales Register"
|
||||
msgstr ""
|
||||
msgstr "Knjiga prodaje po stavkama"
|
||||
|
||||
#: erpnext/stock/get_item_details.py:713
|
||||
msgid "Item/Item Code required to get Item Tax Template."
|
||||
@@ -26035,7 +26040,7 @@ msgstr "Potrebne stavke"
|
||||
#. Label of a Workspace Sidebar Item
|
||||
#: erpnext/workspace_sidebar/subcontracting.json
|
||||
msgid "Items To Be Received"
|
||||
msgstr ""
|
||||
msgstr "Stavke za prijem"
|
||||
|
||||
#. Label of a Link in the Buying Workspace
|
||||
#. Name of a report
|
||||
@@ -28327,7 +28332,7 @@ msgstr "Izdavanje materijala"
|
||||
#. Label of a Workspace Sidebar Item
|
||||
#: erpnext/workspace_sidebar/manufacturing.json
|
||||
msgid "Material Planning"
|
||||
msgstr ""
|
||||
msgstr "Planiranje materijala"
|
||||
|
||||
#. Option for the 'Purpose' (Select) field in DocType 'Stock Entry'
|
||||
#. Option for the 'Purpose' (Select) field in DocType 'Stock Entry Type'
|
||||
@@ -28605,7 +28610,7 @@ msgstr "Materijal ka dobavljaču"
|
||||
#. Label of a Workspace Sidebar Item
|
||||
#: erpnext/workspace_sidebar/subcontracting.json
|
||||
msgid "Materials To Be Transferred"
|
||||
msgstr ""
|
||||
msgstr "Materijal za prenos"
|
||||
|
||||
#: erpnext/controllers/subcontracting_controller.py:1569
|
||||
msgid "Materials are already received against the {0} {1}"
|
||||
@@ -28851,7 +28856,7 @@ msgstr "Poruke duže od 160 karaktera biće podeljene u više poruka"
|
||||
|
||||
#: erpnext/setup/install.py:127
|
||||
msgid "Messaging CRM Campaign"
|
||||
msgstr ""
|
||||
msgstr "CRM kampanja za poruke"
|
||||
|
||||
#. Name of a UOM
|
||||
#: erpnext/setup/setup_wizard/data/uom_data.json
|
||||
@@ -29148,7 +29153,7 @@ msgstr "Nedostajući račun"
|
||||
|
||||
#: erpnext/assets/doctype/asset_category/asset_category.py:191
|
||||
msgid "Missing Accounts"
|
||||
msgstr ""
|
||||
msgstr "Nedostajući računi"
|
||||
|
||||
#: erpnext/accounts/doctype/sales_invoice/sales_invoice.py:430
|
||||
msgid "Missing Asset"
|
||||
@@ -29193,7 +29198,7 @@ msgstr "Nedostaje broj serije paketa"
|
||||
|
||||
#: erpnext/assets/doctype/asset_category/asset_category.py:156
|
||||
msgid "Missing account configuration for company <b>{0}</b>."
|
||||
msgstr ""
|
||||
msgstr "Nedostaje konfiguracija računa za kompaniju <b>{0}</b>."
|
||||
|
||||
#: erpnext/stock/doctype/delivery_trip/delivery_trip.js:154
|
||||
msgid "Missing email template for dispatch. Please set one in Delivery Settings."
|
||||
@@ -29613,7 +29618,7 @@ msgstr "Analiza potrebna"
|
||||
#. Name of a report
|
||||
#: erpnext/stock/report/negative_batch_report/negative_batch_report.json
|
||||
msgid "Negative Batch Report"
|
||||
msgstr ""
|
||||
msgstr "Izveštaj o šaržama sa negativnim stanjem"
|
||||
|
||||
#: erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.py:622
|
||||
msgid "Negative Quantity is not allowed"
|
||||
@@ -30015,7 +30020,7 @@ msgstr "Novi rashodi"
|
||||
|
||||
#: erpnext/accounts/notification/notification_for_new_fiscal_year/notification_for_new_fiscal_year.html:1
|
||||
msgid "New Fiscal Year - {0}"
|
||||
msgstr ""
|
||||
msgstr "Nova fiskalna godina - {0}"
|
||||
|
||||
#. Label of the income (Check) field in DocType 'Email Digest'
|
||||
#: erpnext/setup/doctype/email_digest/email_digest.json
|
||||
@@ -31440,7 +31445,7 @@ msgstr "Stavka početne fakture"
|
||||
#. Label of a Workspace Sidebar Item
|
||||
#: erpnext/workspace_sidebar/accounts_setup.json
|
||||
msgid "Opening Invoice Tool"
|
||||
msgstr ""
|
||||
msgstr "Alat za unos početnih faktura"
|
||||
|
||||
#: erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py:1646
|
||||
#: erpnext/accounts/doctype/sales_invoice/sales_invoice.py:1990
|
||||
@@ -32211,7 +32216,7 @@ msgstr "Izlazno"
|
||||
#. Label of a Workspace Sidebar Item
|
||||
#: erpnext/workspace_sidebar/subcontracting.json
|
||||
msgid "Outward Order"
|
||||
msgstr ""
|
||||
msgstr "Nalog za izdavanje"
|
||||
|
||||
#. Label of the over_billing_allowance (Currency) field in DocType 'Accounts
|
||||
#. Settings'
|
||||
@@ -33926,7 +33931,7 @@ msgstr "Plaćanje primljeno"
|
||||
#. Label of a Workspace Sidebar Item
|
||||
#: erpnext/workspace_sidebar/payments.json
|
||||
msgid "Payment Reconciliaition"
|
||||
msgstr ""
|
||||
msgstr "Usklađivanje plaćanja"
|
||||
|
||||
#. Name of a DocType
|
||||
#. Label of the payment_reconciliation (Table) field in DocType 'POS Closing
|
||||
@@ -35489,7 +35494,7 @@ msgstr "Molimo Vas da osvežite ili resetujete Plaid vezu sa bankom {}."
|
||||
|
||||
#: erpnext/accounts/notification/notification_for_new_fiscal_year/notification_for_new_fiscal_year.html:43
|
||||
msgid "Please review the {0} configuration and complete any required financial setup activities."
|
||||
msgstr ""
|
||||
msgstr "Pogledajte konfiguraciju {0} i dovršite neophodna finansijska podešavanja."
|
||||
|
||||
#: erpnext/accounts/doctype/process_statement_of_accounts/process_statement_of_accounts.js:12
|
||||
#: erpnext/accounts/doctype/process_statement_of_accounts/process_statement_of_accounts.js:28
|
||||
@@ -36578,7 +36583,7 @@ msgstr "Prethodna fiskalna godina nije zatvorena"
|
||||
|
||||
#: erpnext/stock/report/negative_batch_report/negative_batch_report.py:54
|
||||
msgid "Previous Qty"
|
||||
msgstr ""
|
||||
msgstr "Prethodna količina"
|
||||
|
||||
#. Label of the previous_work_experience (Section Break) field in DocType
|
||||
#. 'Employee'
|
||||
@@ -40652,7 +40657,7 @@ msgstr "Veličina reda za usklađivanje"
|
||||
#. Label of a Workspace Sidebar Item
|
||||
#: erpnext/workspace_sidebar/banking.json
|
||||
msgid "Reconciliation Statement"
|
||||
msgstr ""
|
||||
msgstr "Izveštaj o usklađenosti"
|
||||
|
||||
#. Label of the reconciliation_takes_effect_on (Select) field in DocType
|
||||
#. 'Company'
|
||||
@@ -40941,7 +40946,7 @@ msgstr "Regionalni"
|
||||
#. Label of a Workspace Sidebar Item
|
||||
#: erpnext/workspace_sidebar/financial_reports.json
|
||||
msgid "Registers"
|
||||
msgstr ""
|
||||
msgstr "Registri"
|
||||
|
||||
#. Label of the registration_details (Code) field in DocType 'Company'
|
||||
#: erpnext/setup/doctype/company/company.json
|
||||
@@ -43127,7 +43132,7 @@ msgstr "Red #{0}: Nalog knjiženja {1} ne sadrži račun {2} ili je već povezan
|
||||
|
||||
#: erpnext/assets/doctype/asset_category/asset_category.py:149
|
||||
msgid "Row #{0}: Missing <b>{1}</b> for company <b>{2}</b>."
|
||||
msgstr ""
|
||||
msgstr "Red #{0}: Nedostaje <b>{1}</b> za kompaniju <b>{2}</b>."
|
||||
|
||||
#: erpnext/assets/doctype/asset/asset.py:678
|
||||
msgid "Row #{0}: Next Depreciation Date cannot be before Available-for-use Date"
|
||||
@@ -47596,7 +47601,7 @@ msgstr "Simultano"
|
||||
|
||||
#: erpnext/assets/doctype/asset_category/asset_category.py:183
|
||||
msgid "Since there are active depreciable assets under this category, the following accounts are required. <br><br>"
|
||||
msgstr ""
|
||||
msgstr "Pošto postoje aktivna sredstva koja se amortizuju u ovoj kategoriji, sledeći računi su obavezni. <br><br>"
|
||||
|
||||
#: erpnext/stock/doctype/stock_entry/stock_entry.py:688
|
||||
msgid "Since there is a process loss of {0} units for the finished good {1}, you should reduce the quantity by {0} units for the finished good {1} in the Items Table."
|
||||
@@ -49958,7 +49963,7 @@ msgstr "Vreme isporuke dobavljača (dani)"
|
||||
#. Label of a Workspace Sidebar Item
|
||||
#: erpnext/workspace_sidebar/financial_reports.json
|
||||
msgid "Supplier Ledger"
|
||||
msgstr ""
|
||||
msgstr "Knjiga dobavljača"
|
||||
|
||||
#. Name of a report
|
||||
#. Label of a Link in the Financial Reports Workspace
|
||||
@@ -50854,7 +50859,7 @@ msgstr "Podešavanje poreza"
|
||||
#. Label of a Workspace Sidebar Item
|
||||
#: erpnext/workspace_sidebar/selling.json
|
||||
msgid "Tax Template"
|
||||
msgstr ""
|
||||
msgstr "Poreski šablon"
|
||||
|
||||
#: erpnext/accounts/doctype/tax_rule/tax_rule.py:83
|
||||
msgid "Tax Template is mandatory."
|
||||
@@ -51689,7 +51694,7 @@ msgstr "Polja od vlasnika i ka vlasniku ne mogu biti prazna"
|
||||
|
||||
#: erpnext/accounts/notification/notification_for_new_fiscal_year/notification_for_new_fiscal_year.html:40
|
||||
msgid "The fiscal year has been automatically created in a Disabled state to maintain consistency with the previous fiscal year's status."
|
||||
msgstr ""
|
||||
msgstr "Fiskalna godina je automatski kreirana u onemogućenom statusu radi usklađenosti sa statusom prethodne fiskalne godine."
|
||||
|
||||
#: erpnext/accounts/doctype/share_transfer/share_transfer.py:240
|
||||
msgid "The folio numbers are not matching"
|
||||
@@ -53907,7 +53912,7 @@ msgstr "Naziv transakcije"
|
||||
|
||||
#: erpnext/stock/report/negative_batch_report/negative_batch_report.py:60
|
||||
msgid "Transaction Qty"
|
||||
msgstr ""
|
||||
msgstr "Transakciona količina"
|
||||
|
||||
#. Label of the transaction_settings_section (Tab Break) field in DocType
|
||||
#. 'Buying Settings'
|
||||
@@ -57437,7 +57442,7 @@ msgstr "Možete promeniti matični račun u račun bilansa stanja ili izabrati d
|
||||
|
||||
#: erpnext/assets/doctype/asset_category/asset_category.py:186
|
||||
msgid "You can either configure default depreciation accounts in the Company or set the required accounts in the following rows: <br><br>"
|
||||
msgstr ""
|
||||
msgstr "Možete konfigurisati podrazumevane račune amortizacije u podešavanjima kompanije ili uneti potrebne račune u sledećim redovima: <br><br>"
|
||||
|
||||
#: erpnext/accounts/doctype/journal_entry/journal_entry.py:703
|
||||
msgid "You can not enter current voucher in 'Against Journal Entry' column"
|
||||
@@ -57682,7 +57687,7 @@ msgstr "kao procenat količine finalne stavke"
|
||||
|
||||
#: erpnext/stock/doctype/serial_and_batch_bundle/serial_and_batch_bundle.py:1472
|
||||
msgid "as of {0}"
|
||||
msgstr ""
|
||||
msgstr "na dan {0}"
|
||||
|
||||
#: erpnext/www/book_appointment/index.html:43
|
||||
msgid "at"
|
||||
@@ -58283,7 +58288,7 @@ msgstr "{0} jedinica stavke {1} nije dostupno ni u jednom skladištu."
|
||||
|
||||
#: erpnext/stock/doctype/pick_list/pick_list.py:1009
|
||||
msgid "{0} units of Item {1} is not available in any of the warehouses. Other Pick Lists exist for this item."
|
||||
msgstr ""
|
||||
msgstr "{0} jedinica stavke {1} nije dostupno ni u jednom skladištu. Postoje druge liste za odabir za ovu stavku."
|
||||
|
||||
#: erpnext/stock/doctype/stock_ledger_entry/stock_ledger_entry.py:144
|
||||
msgid "{0} units of {1} are required in {2} with the inventory dimension: {3} on {4} {5} for {6} to complete the transaction."
|
||||
|
||||
@@ -3,7 +3,7 @@ msgstr ""
|
||||
"Project-Id-Version: frappe\n"
|
||||
"Report-Msgid-Bugs-To: hello@frappe.io\n"
|
||||
"POT-Creation-Date: 2026-02-22 09:43+0000\n"
|
||||
"PO-Revision-Date: 2026-02-24 16:58\n"
|
||||
"PO-Revision-Date: 2026-02-27 16:51\n"
|
||||
"Last-Translator: hello@frappe.io\n"
|
||||
"Language-Team: Swedish\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
@@ -28,7 +28,7 @@ msgid "\n"
|
||||
msgstr "\n"
|
||||
"\t\t\tParti {0} av artikel {1} har negativt lager på lager {2}{3}.\n"
|
||||
"\t\t\tLägg till lager kvantitet på {4} för att gå vidare med denna post.\n"
|
||||
"\t\t\tOm det inte är möjligt att göra justering postering, aktivera \"Tillåt Negativt Lager för Parti\" i Lager Inställningar för att fortsätta.\n"
|
||||
"\t\t\tOm det inte är möjligt att göra justering post, aktivera \"Tillåt Negativt Lager för Parti\" i Lager Inställningar för att fortsätta.\n"
|
||||
"\t\t\tVid aktivering av denna inställning kan det dock leda till negativt lager i system.\n"
|
||||
"\t\t\tSe till att lager nivåer justeras så snart som möjligt för att bibehålla korrekt grund pris."
|
||||
|
||||
@@ -2027,7 +2027,7 @@ msgstr "Bokföring"
|
||||
#: erpnext/accounts/doctype/accounts_settings/accounts_settings.json
|
||||
#: erpnext/setup/doctype/company/company.json
|
||||
msgid "Accounts Closing"
|
||||
msgstr "Bokföring Stängning"
|
||||
msgstr "Bokföring Period"
|
||||
|
||||
#. Label of the accounts_frozen_till_date (Date) field in DocType 'Company'
|
||||
#: erpnext/setup/doctype/company/company.json
|
||||
@@ -3459,7 +3459,7 @@ msgstr "Mot Intäkt Konto"
|
||||
#: erpnext/accounts/doctype/journal_entry/journal_entry.py:729
|
||||
#: erpnext/accounts/doctype/payment_entry/payment_entry.py:776
|
||||
msgid "Against Journal Entry {0} does not have any unmatched {1} entry"
|
||||
msgstr "Mot Journal Post {0} som inte har någon oavstämd {1} post"
|
||||
msgstr "Mot Journal Post {0} som inte har någon ej avstämd {1} post"
|
||||
|
||||
#: erpnext/accounts/doctype/gl_entry/gl_entry.py:393
|
||||
msgid "Against Journal Entry {0} is already adjusted against some other voucher"
|
||||
@@ -5278,13 +5278,13 @@ msgstr "Arshin"
|
||||
#: erpnext/stock/report/stock_ageing/stock_ageing.js:16
|
||||
#: erpnext/stock/report/stock_and_account_value_comparison/stock_and_account_value_comparison.js:30
|
||||
msgid "As On Date"
|
||||
msgstr "Som den"
|
||||
msgstr "Datum"
|
||||
|
||||
#: erpnext/accounts/report/billed_items_to_be_received/billed_items_to_be_received.js:15
|
||||
#: erpnext/accounts/report/delivered_items_to_be_billed/delivered_items_to_be_billed.js:15
|
||||
#: erpnext/accounts/report/received_items_to_be_billed/received_items_to_be_billed.js:15
|
||||
msgid "As on Date"
|
||||
msgstr "Som den"
|
||||
msgstr "Datum"
|
||||
|
||||
#. Description of the 'Finished Good Quantity ' (Float) field in DocType 'Stock
|
||||
#. Entry'
|
||||
@@ -13245,7 +13245,7 @@ msgstr "Aktuell Lager"
|
||||
#. Reconciliation Item'
|
||||
#: erpnext/stock/doctype/stock_reconciliation_item/stock_reconciliation_item.json
|
||||
msgid "Current Valuation Rate"
|
||||
msgstr "Aktuell Värderingssats"
|
||||
msgstr "Aktuell Grund Pris"
|
||||
|
||||
#: erpnext/selling/report/sales_analytics/sales_analytics.js:90
|
||||
msgid "Curves"
|
||||
@@ -17605,7 +17605,7 @@ msgstr "Aktivera System Övervakning"
|
||||
#. Settings'
|
||||
#: erpnext/accounts/doctype/accounts_settings/accounts_settings.json
|
||||
msgid "Enable Immutable Ledger"
|
||||
msgstr "Aktivera Oförenderlig Register"
|
||||
msgstr "Aktivera Oförenderlig Bokföring"
|
||||
|
||||
#. Label of the enable_item_wise_inventory_account (Check) field in DocType
|
||||
#. 'Company'
|
||||
@@ -19659,7 +19659,7 @@ msgstr "För projekt {0}, uppdatera din status"
|
||||
#: erpnext/manufacturing/doctype/master_production_schedule/master_production_schedule.json
|
||||
#: erpnext/manufacturing/doctype/sales_forecast/sales_forecast.json
|
||||
msgid "For projected and forecast quantities, the system will consider all child warehouses under the selected parent warehouse."
|
||||
msgstr "För beräknade och prognostiserade kvantiteter kommer system att inkludera alla underordnade lager under vald överordnad lager."
|
||||
msgstr "För beräknade och förväntade kvantiteter kommer system att inkludera alla underordnade lager under vald överordnad lager."
|
||||
|
||||
#: erpnext/stock/doctype/stock_entry/stock_entry.py:1703
|
||||
msgid "For quantity {0} should not be greater than allowed quantity {1}"
|
||||
@@ -20744,7 +20744,7 @@ msgstr "Hämta Tidrapporter"
|
||||
#: erpnext/accounts/doctype/payment_reconciliation/payment_reconciliation.js:102
|
||||
#: erpnext/accounts/doctype/payment_reconciliation/payment_reconciliation.js:107
|
||||
msgid "Get Unreconciled Entries"
|
||||
msgstr "Hämta Oavstämda Poster"
|
||||
msgstr "Hämta Ej Avstämda Poster"
|
||||
|
||||
#: erpnext/stock/doctype/delivery_trip/delivery_trip.js:69
|
||||
msgid "Get stops from"
|
||||
@@ -21890,7 +21890,7 @@ msgstr "Om aktiverad kommer Konsoliderad Faktura att ha avrundad totalt inaktive
|
||||
#. field in DocType 'Stock Settings'
|
||||
#: erpnext/stock/doctype/stock_settings/stock_settings.json
|
||||
msgid "If enabled, the item rate won't adjust to the valuation rate during internal transfers, but accounting will still use the valuation rate."
|
||||
msgstr "Om aktiverad, kommer artikel pris inte att anpassas till värderingssats vid interna överföringar, men bokföring kommer fortfarande att använda värderingssats."
|
||||
msgstr "Om aktiverad, kommer artikel pris inte att sättas till grund pris vid interna överföringar, men bokföring kommer fortfarande att använda grund pris."
|
||||
|
||||
#. Description of the 'Validate Material Transfer Warehouses' (Check) field in
|
||||
#. DocType 'Stock Settings'
|
||||
@@ -22015,7 +22015,7 @@ msgstr "Om konto är låst, tillåts poster för Behöriga Användare."
|
||||
|
||||
#: erpnext/stock/stock_ledger.py:1999
|
||||
msgid "If the item is transacting as a Zero Valuation Rate item in this entry, please enable 'Allow Zero Valuation Rate' in the {0} Item table."
|
||||
msgstr "Om artikel handlas som Noll Värderingssats i denna post, aktivera 'Tillåt Noll Värderingssats' i {0} Artikel Tabell."
|
||||
msgstr "Om artikel handlas som Noll Grund Pris i denna post, aktivera 'Tillåt Noll Grund Pris' i {0} Artikel Tabell."
|
||||
|
||||
#. Description of the 'Projected On Hand' (Float) field in DocType 'Material
|
||||
#. Request Item'
|
||||
@@ -22084,7 +22084,7 @@ msgstr "Om vald kan flera material användas för en Arbetsorder. Detta är anv
|
||||
|
||||
#: erpnext/manufacturing/doctype/manufacturing_settings/manufacturing_settings.js:24
|
||||
msgid "If ticked, the BOM cost will be automatically updated based on Valuation Rate / Price List Rate / last purchase rate of raw materials."
|
||||
msgstr "Om vald uppdateras Stycklista Kostnad automatiskt baserat på Värderingssats / Prislista Pris / Senaste Inköp Pris för Råmaterial."
|
||||
msgstr "Om vald uppdateras Stycklista Kostnad automatiskt baserat på Grund Pris / Prislista Pris / Senaste Inköp Pris för Råmaterial."
|
||||
|
||||
#: erpnext/accounts/doctype/pricing_rule/pricing_rule.js:46
|
||||
msgid "If two or more Pricing Rules are found based on the above conditions, Priority is applied. Priority is a number between 0 to 20 while default value is zero (blank). Higher number means it will take precedence if there are multiple Pricing Rules with same conditions."
|
||||
@@ -25828,7 +25828,7 @@ msgstr "Artikel kvantitet kan inte uppdateras eftersom råmaterial redan är bea
|
||||
|
||||
#: erpnext/stock/doctype/stock_entry/stock_entry.py:1149
|
||||
msgid "Item rate has been updated to zero as Allow Zero Valuation Rate is checked for item {0}"
|
||||
msgstr "Artikel pris har ändrats till noll eftersom Tillåt Noll Värderingssats är vald för artikel {0}"
|
||||
msgstr "Artikel pris har ändrats till noll eftersom Tillåt Noll Grund Pris är vald för artikel {0}"
|
||||
|
||||
#. Label of the finished_good (Link) field in DocType 'Job Card'
|
||||
#: erpnext/manufacturing/doctype/job_card/job_card.json
|
||||
@@ -25842,7 +25842,7 @@ msgstr "Artikel som ska produceras eller packas om"
|
||||
|
||||
#: erpnext/stock/doctype/landed_cost_voucher/landed_cost_voucher.js:9
|
||||
msgid "Item valuation rate is recalculated considering landed cost voucher amount"
|
||||
msgstr "Värderingssats räknas om med hänsyn till landad kostnad verifikat belopp"
|
||||
msgstr "Grund Pris räknas om med hänsyn till landad kostnad verifikat belopp"
|
||||
|
||||
#: erpnext/stock/utils.py:531
|
||||
msgid "Item valuation reposting in progress. Report might show incorrect item valuation."
|
||||
@@ -26073,7 +26073,7 @@ msgstr "Artiklar hittades inte."
|
||||
|
||||
#: erpnext/stock/doctype/stock_entry/stock_entry.py:1145
|
||||
msgid "Items rate has been updated to zero as Allow Zero Valuation Rate is checked for the following items: {0}"
|
||||
msgstr "Artikel Pris har ändrats till noll eftersom Tillåt Noll Värderingssats är vald för följande artiklar: {0}"
|
||||
msgstr "Artikel Pris har ändrats till noll eftersom Tillåt Noll Grund Pris är vald för följande artiklar: {0}"
|
||||
|
||||
#. Label of the items_to_be_repost (Code) field in DocType 'Repost Item
|
||||
#. Valuation'
|
||||
@@ -29629,7 +29629,7 @@ msgstr "Negativt Lager Fel"
|
||||
|
||||
#: erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.py:627
|
||||
msgid "Negative Valuation Rate is not allowed"
|
||||
msgstr "Negativ Värderingssats är inte tillåtet"
|
||||
msgstr "Negativ Grund Pris är inte tillåtet"
|
||||
|
||||
#: erpnext/setup/setup_wizard/data/sales_stage.txt:8
|
||||
#: erpnext/setup/setup_wizard/operations/install_fixtures.py:439
|
||||
@@ -30285,11 +30285,11 @@ msgstr "Inga Villkor"
|
||||
|
||||
#: erpnext/accounts/doctype/payment_reconciliation/payment_reconciliation.js:236
|
||||
msgid "No Unreconciled Invoices and Payments found for this party and account"
|
||||
msgstr "Inga Oavstämda Fakturor och Betalningar hittades för denna parti och konto"
|
||||
msgstr "Inga Ej Avstämda Fakturor och Betalningar hittades för denna parti och konto"
|
||||
|
||||
#: erpnext/accounts/doctype/payment_reconciliation/payment_reconciliation.js:241
|
||||
msgid "No Unreconciled Payments found for this party"
|
||||
msgstr "Inga Oavstämda Betalningar hittades för denna parti"
|
||||
msgstr "Inga Ej Avstämda Betalningar hittades för denna parti"
|
||||
|
||||
#: erpnext/manufacturing/doctype/production_plan/production_plan.py:782
|
||||
#: erpnext/subcontracting/doctype/subcontracting_inward_order/subcontracting_inward_order.py:250
|
||||
@@ -30524,7 +30524,7 @@ msgstr "Inga rader med noll dokument antal hittades"
|
||||
|
||||
#: erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.py:804
|
||||
msgid "No stock ledger entries were created. Please set the quantity or valuation rate for the items properly and try again."
|
||||
msgstr "Inga Lager Register Poster har skapats. Ange kvantitet eller grund pris för artiklar på rätt sätt och försök igen."
|
||||
msgstr "Inga Lager Register Poster skapade. Ange kvantitet eller grund pris för artiklar på rätt sätt och försök igen."
|
||||
|
||||
#. Description of the 'Stock Frozen Up To' (Date) field in DocType 'Stock
|
||||
#. Settings'
|
||||
@@ -40662,7 +40662,7 @@ msgstr "Avstämning Rapport"
|
||||
#. 'Company'
|
||||
#: erpnext/setup/doctype/company/company.json
|
||||
msgid "Reconciliation Takes Effect On"
|
||||
msgstr "Avstämning Träder i Kraft"
|
||||
msgstr "Avstämning tar effekt på"
|
||||
|
||||
#. Label of the recording_html (HTML) field in DocType 'Call Log'
|
||||
#: erpnext/telephony/doctype/call_log/call_log.json
|
||||
@@ -43701,7 +43701,7 @@ msgstr "Rad # {0}: Artikel Moms Mall uppdaterad enligt giltighet och tillämpad
|
||||
|
||||
#: erpnext/controllers/selling_controller.py:633
|
||||
msgid "Row {0}: Item rate has been updated as per valuation rate since its an internal stock transfer"
|
||||
msgstr "Rad # {0}: Artikel Pris är uppdaterad enligt Värderingssats eftersom det är intern lager överföring"
|
||||
msgstr "Rad # {0}: Artikel Pris är uppdaterad enligt Grund Pris eftersom det är intern lager överföring"
|
||||
|
||||
#: erpnext/controllers/subcontracting_controller.py:151
|
||||
msgid "Row {0}: Item {1} must be a stock item."
|
||||
@@ -51895,7 +51895,7 @@ msgstr "Aktier finns inte med {0}"
|
||||
|
||||
#: erpnext/stock/stock_ledger.py:801
|
||||
msgid "The stock for the item {0} in the {1} warehouse was negative on the {2}. You should create a positive entry {3} before the date {4} and time {5} to post the correct valuation rate. For more details, please read the <a href='https://docs.erpnext.com/docs/user/manual/en/stock-adjustment-cogs-with-negative-stock'>documentation<a>."
|
||||
msgstr "Lager för artikel {0} i {1} lager var negativt {2}. Skapa positiv post {3} före {4} och {5} för att bokföra rätt Värderingssats. För mer information, läs dokumentation <a href='https://docs.erpnext.com/docs/user/manual/en/stock-adjustment-cogs-with-negative-stock'><a>."
|
||||
msgstr "Lager för artikel {0} i {1} lager var negativt {2}. Skapa positiv post {3} före {4} och {5} för att bokföra rätt grund pris. För mer information, läs dokumentation <a href='https://docs.erpnext.com/docs/user/manual/en/stock-adjustment-cogs-with-negative-stock'><a>."
|
||||
|
||||
#: erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.py:731
|
||||
msgid "The stock has been reserved for the following Items and Warehouses, un-reserve the same to {0} the Stock Reconciliation: <br /><br /> {1}"
|
||||
@@ -55547,7 +55547,7 @@ msgstr "Validera Prissättning Regel"
|
||||
#. Settings'
|
||||
#: erpnext/selling/doctype/selling_settings/selling_settings.json
|
||||
msgid "Validate Selling Price for Item Against Purchase Rate or Valuation Rate"
|
||||
msgstr "Validera Försäljning Pris för Artikel mot Inköp Pris eller Värderingssats"
|
||||
msgstr "Validera Försäljning Pris för Artikel mot Inköp Pris eller Grund Pris"
|
||||
|
||||
#. Label of the validate_stock_on_save (Check) field in DocType 'POS Profile'
|
||||
#: erpnext/accounts/doctype/pos_profile/pos_profile.json
|
||||
@@ -55666,7 +55666,7 @@ msgstr "Grund Pris erfordras för Artikel {0} på rad {1}"
|
||||
#. 'Purchase Taxes and Charges'
|
||||
#: erpnext/accounts/doctype/purchase_taxes_and_charges/purchase_taxes_and_charges.json
|
||||
msgid "Valuation and Total"
|
||||
msgstr "Värdering och Totalt"
|
||||
msgstr "Grund Pris och Totalt"
|
||||
|
||||
#: erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.py:1003
|
||||
msgid "Valuation rate for customer provided items has been set to zero."
|
||||
@@ -56833,7 +56833,7 @@ msgstr "När detta alternativ är aktiverad använder system dokument registreri
|
||||
|
||||
#: erpnext/stock/doctype/item/item.js:1079
|
||||
msgid "When creating an Item, entering a value for this field will automatically create an Item Price at the backend."
|
||||
msgstr "När du skapar en artikel, om du anger ett värde för detta fält, skapas automatiskt ett artikelpris i bakgrund."
|
||||
msgstr "När artikel skapas, om värde är angiven för detta fält, skapas artikel pris automatiskt i bakgrunden."
|
||||
|
||||
#: erpnext/stock/doctype/stock_entry/stock_entry.py:294
|
||||
msgid "When there are multiple finished goods ({0}) in a Repack stock entry, the basic rate for all finished goods must be set manually. To set rate manually, enable the checkbox 'Set Basic Rate Manually' in the respective finished good row."
|
||||
|
||||
@@ -405,9 +405,11 @@ class MaintenanceSchedule(TransactionBase):
|
||||
delete_events(self.doctype, self.name)
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_pending_data(self, data_type, s_date=None, item_name=None):
|
||||
def get_pending_data(self, data_type: str, s_date: str | None = None, item_name: str | None = None):
|
||||
if data_type == "date":
|
||||
dates = ""
|
||||
if not item_name:
|
||||
frappe.throw(_("Item Name is required."))
|
||||
for schedule in self.schedules:
|
||||
if schedule.item_name == item_name and schedule.completion_status == "Pending":
|
||||
dates = dates + "\n" + formatdate(schedule.scheduled_date, "dd-MM-yyyy")
|
||||
@@ -421,6 +423,8 @@ class MaintenanceSchedule(TransactionBase):
|
||||
break
|
||||
return items
|
||||
elif data_type == "id":
|
||||
if not s_date:
|
||||
frappe.throw(_("Scheduled Date is required."))
|
||||
for schedule in self.schedules:
|
||||
if schedule.item_name == item_name and s_date == formatdate(
|
||||
schedule.scheduled_date, "dd-mm-yyyy"
|
||||
@@ -429,12 +433,10 @@ class MaintenanceSchedule(TransactionBase):
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_serial_nos_from_schedule(item_code, schedule=None):
|
||||
serial_nos = []
|
||||
if schedule:
|
||||
serial_nos = frappe.db.get_value(
|
||||
"Maintenance Schedule Item", {"parent": schedule, "item_code": item_code}, "serial_no"
|
||||
)
|
||||
def get_serial_nos_from_schedule(item_code: str, schedule: str):
|
||||
serial_nos = frappe.db.get_value(
|
||||
"Maintenance Schedule Item", {"parent": schedule, "item_code": item_code}, "serial_no"
|
||||
)
|
||||
|
||||
if serial_nos:
|
||||
serial_nos = get_serial_nos(serial_nos)
|
||||
@@ -443,7 +445,12 @@ def get_serial_nos_from_schedule(item_code, schedule=None):
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
def make_maintenance_visit(source_name, target_doc=None, item_name=None, s_id=None):
|
||||
def make_maintenance_visit(
|
||||
source_name: str,
|
||||
target_doc: str | dict | None = None,
|
||||
item_name: str | None = None,
|
||||
s_id: str | None = None,
|
||||
):
|
||||
from frappe.model.mapper import get_mapped_doc
|
||||
|
||||
def condition(doc):
|
||||
|
||||
@@ -1322,9 +1322,9 @@ class JobCard(Document):
|
||||
|
||||
def is_work_order_closed(self):
|
||||
if self.work_order:
|
||||
status = frappe.get_value("Work Order", self.work_order)
|
||||
status = frappe.get_value("Work Order", self.work_order, "status")
|
||||
|
||||
if status == "Closed":
|
||||
if status in ["Closed", "Stopped"]:
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
@@ -225,7 +225,12 @@ class WorkOrder(Document):
|
||||
frappe.throw(_("Actual End Date cannot be before Actual Start Date"))
|
||||
|
||||
def validate_fg_warehouse_for_reservation(self):
|
||||
if self.reserve_stock and self.sales_order and not self.subcontracting_inward_order:
|
||||
if (
|
||||
self.reserve_stock
|
||||
and self.sales_order
|
||||
and not self.subcontracting_inward_order
|
||||
and not self.production_plan_sub_assembly_item
|
||||
):
|
||||
warehouses = frappe.get_all(
|
||||
"Sales Order Item",
|
||||
filters={"parent": self.sales_order, "item_code": self.production_item},
|
||||
@@ -413,39 +418,52 @@ class WorkOrder(Document):
|
||||
)
|
||||
|
||||
def validate_sales_order(self):
|
||||
if self.production_plan_sub_assembly_item:
|
||||
return
|
||||
|
||||
if self.sales_order:
|
||||
self.check_sales_order_on_hold_or_close()
|
||||
so = frappe.db.sql(
|
||||
"""
|
||||
select so.name, so_item.delivery_date, so.project
|
||||
from `tabSales Order` so
|
||||
inner join `tabSales Order Item` so_item on so_item.parent = so.name
|
||||
left join `tabProduct Bundle Item` pk_item on so_item.item_code = pk_item.parent
|
||||
where so.name=%s and so.docstatus = 1
|
||||
and so.skip_delivery_note = 0 and (
|
||||
so_item.item_code=%s or
|
||||
pk_item.item_code=%s )
|
||||
""",
|
||||
(self.sales_order, self.production_item, self.production_item),
|
||||
as_dict=1,
|
||||
|
||||
SalesOrder = frappe.qb.DocType("Sales Order")
|
||||
SalesOrderItem = frappe.qb.DocType("Sales Order Item")
|
||||
PackedItem = frappe.qb.DocType("Packed Item")
|
||||
ProductBundleItem = frappe.qb.DocType("Product Bundle Item")
|
||||
|
||||
so = (
|
||||
frappe.qb.from_(SalesOrder)
|
||||
.inner_join(SalesOrderItem)
|
||||
.on(SalesOrderItem.parent == SalesOrder.name)
|
||||
.left_join(ProductBundleItem)
|
||||
.on(ProductBundleItem.parent == SalesOrderItem.item_code)
|
||||
.select(SalesOrder.name, SalesOrder.project, SalesOrderItem.delivery_date)
|
||||
.where(
|
||||
(SalesOrder.skip_delivery_note == 0)
|
||||
& (SalesOrder.docstatus == 1)
|
||||
& (SalesOrder.name == self.sales_order)
|
||||
& (
|
||||
(SalesOrderItem.item_code == self.production_item)
|
||||
| (ProductBundleItem.item_code == self.production_item)
|
||||
)
|
||||
)
|
||||
.run(as_dict=1)
|
||||
)
|
||||
|
||||
if not so:
|
||||
so = frappe.db.sql(
|
||||
"""
|
||||
select
|
||||
so.name, so_item.delivery_date, so.project
|
||||
from
|
||||
`tabSales Order` so, `tabSales Order Item` so_item, `tabPacked Item` packed_item
|
||||
where so.name=%s
|
||||
and so.name=so_item.parent
|
||||
and so.name=packed_item.parent
|
||||
and so.skip_delivery_note = 0
|
||||
and so_item.item_code = packed_item.parent_item
|
||||
and so.docstatus = 1 and packed_item.item_code=%s
|
||||
""",
|
||||
(self.sales_order, self.production_item),
|
||||
as_dict=1,
|
||||
so = (
|
||||
frappe.qb.from_(SalesOrder)
|
||||
.inner_join(SalesOrderItem)
|
||||
.on(SalesOrderItem.parent == SalesOrder.name)
|
||||
.inner_join(PackedItem)
|
||||
.on(PackedItem.parent == SalesOrder.name)
|
||||
.select(SalesOrder.name, SalesOrder.project, SalesOrderItem.delivery_date)
|
||||
.where(
|
||||
(SalesOrder.name == self.sales_order)
|
||||
& (SalesOrder.skip_delivery_note == 0)
|
||||
& (SalesOrderItem.item_code == PackedItem.parent_item)
|
||||
& (SalesOrder.docstatus == 1)
|
||||
& (PackedItem.item_code == self.production_item)
|
||||
)
|
||||
.run(as_dict=1)
|
||||
)
|
||||
|
||||
if len(so):
|
||||
@@ -651,7 +669,7 @@ class WorkOrder(Document):
|
||||
|
||||
from erpnext.selling.doctype.sales_order.sales_order import update_produced_qty_in_so_item
|
||||
|
||||
if self.sales_order and self.sales_order_item:
|
||||
if self.sales_order and self.sales_order_item and not self.production_plan_sub_assembly_item:
|
||||
update_produced_qty_in_so_item(self.sales_order, self.sales_order_item)
|
||||
|
||||
if self.production_plan:
|
||||
@@ -695,19 +713,25 @@ class WorkOrder(Document):
|
||||
self.db_set("disassembled_qty", self.disassembled_qty)
|
||||
|
||||
def get_transferred_or_manufactured_qty(self, purpose, fieldname):
|
||||
table = frappe.qb.DocType("Stock Entry")
|
||||
query = frappe.qb.from_(table).where(
|
||||
(table.work_order == self.name) & (table.docstatus == 1) & (table.purpose == purpose)
|
||||
parent = frappe.qb.DocType("Stock Entry")
|
||||
|
||||
query = frappe.qb.from_(parent).where(
|
||||
(parent.work_order == self.name)
|
||||
& (parent.docstatus == 1)
|
||||
& (parent.purpose == purpose)
|
||||
& (parent.is_additional_transfer_entry == cint(fieldname == "additional_transferred_qty"))
|
||||
)
|
||||
|
||||
if purpose == "Manufacture":
|
||||
query = query.select(Sum(table.fg_completed_qty) - Sum(table.process_loss_qty))
|
||||
child = frappe.qb.DocType("Stock Entry Detail")
|
||||
query = (
|
||||
query.join(child)
|
||||
.on(parent.name == child.parent)
|
||||
.select(Sum(child.transfer_qty))
|
||||
.where(child.is_finished_item == 1)
|
||||
)
|
||||
else:
|
||||
query = query.select(Sum(table.fg_completed_qty))
|
||||
|
||||
query = query.where(
|
||||
table.is_additional_transfer_entry == cint(fieldname == "additional_transferred_qty")
|
||||
)
|
||||
query = query.select(Sum(parent.fg_completed_qty))
|
||||
|
||||
return flt(query.run()[0][0])
|
||||
|
||||
@@ -1159,7 +1183,7 @@ class WorkOrder(Document):
|
||||
doc.db_set("status", doc.status)
|
||||
|
||||
def update_work_order_qty_in_so(self):
|
||||
if not self.sales_order and not self.sales_order_item:
|
||||
if (not self.sales_order and not self.sales_order_item) or self.production_plan_sub_assembly_item:
|
||||
return
|
||||
|
||||
total_bundle_qty = 1
|
||||
@@ -2106,7 +2130,7 @@ def make_stock_reservation_entries(
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
def cancel_stock_reservation_entries(doc, sre_list):
|
||||
def cancel_stock_reservation_entries(doc: str | dict, sre_list: str | list):
|
||||
if isinstance(doc, str):
|
||||
doc = parse_json(doc)
|
||||
doc = frappe.get_doc("Work Order", doc.get("name"))
|
||||
|
||||
@@ -468,4 +468,6 @@ erpnext.patches.v15_0.replace_http_with_https_in_sales_partner
|
||||
erpnext.patches.v16_0.migrate_asset_type_checkboxes_to_select
|
||||
erpnext.patches.v15_0.delete_quotation_lost_record_detail
|
||||
erpnext.patches.v16_0.add_portal_redirects
|
||||
erpnext.patches.v16_0.complete_onboarding_steps_for_older_sites #2
|
||||
erpnext.patches.v16_0.update_order_qty_and_requested_qty_based_on_mr_and_po
|
||||
erpnext.patches.v16_0.complete_onboarding_steps_for_older_sites #2
|
||||
erpnext.patches.v16_0.enable_serial_batch_setting
|
||||
|
||||
9
erpnext/patches/v16_0/enable_serial_batch_setting.py
Normal file
9
erpnext/patches/v16_0/enable_serial_batch_setting.py
Normal file
@@ -0,0 +1,9 @@
|
||||
import frappe
|
||||
|
||||
|
||||
def execute():
|
||||
if not frappe.get_all("Serial No", limit=1) and not frappe.get_all("Batch", limit=1):
|
||||
return
|
||||
|
||||
frappe.db.set_single_value("Stock Settings", "enable_serial_and_batch_no_for_item", 1)
|
||||
frappe.db.set_default("enable_serial_and_batch_no_for_item", 1)
|
||||
@@ -0,0 +1,33 @@
|
||||
import frappe
|
||||
from frappe.query_builder import DocType
|
||||
from frappe.query_builder.functions import Sum
|
||||
|
||||
|
||||
def execute():
|
||||
PurchaseOrderItem = DocType("Purchase Order Item")
|
||||
MaterialRequestItem = DocType("Material Request Item")
|
||||
|
||||
poi_query = (
|
||||
frappe.qb.from_(PurchaseOrderItem)
|
||||
.select(PurchaseOrderItem.sales_order_item, Sum(PurchaseOrderItem.stock_qty))
|
||||
.where(PurchaseOrderItem.sales_order_item.isnotnull() & PurchaseOrderItem.docstatus == 1)
|
||||
.groupby(PurchaseOrderItem.sales_order_item)
|
||||
)
|
||||
|
||||
mri_query = (
|
||||
frappe.qb.from_(MaterialRequestItem)
|
||||
.select(MaterialRequestItem.sales_order_item, Sum(MaterialRequestItem.stock_qty))
|
||||
.where(MaterialRequestItem.sales_order_item.isnotnull() & MaterialRequestItem.docstatus == 1)
|
||||
.groupby(MaterialRequestItem.sales_order_item)
|
||||
)
|
||||
|
||||
poi_data = poi_query.run()
|
||||
mri_data = mri_query.run()
|
||||
|
||||
updates_against_poi = {data[0]: {"ordered_qty": data[1]} for data in poi_data}
|
||||
updates_against_mri = {data[0]: {"requested_qty": data[1], "ordered_qty": 0} for data in mri_data}
|
||||
|
||||
frappe.db.auto_commit_on_many_writes = 1
|
||||
frappe.db.bulk_update("Sales Order Item", updates_against_mri)
|
||||
frappe.db.bulk_update("Sales Order Item", updates_against_poi)
|
||||
frappe.db.auto_commit_on_many_writes = 0
|
||||
@@ -205,7 +205,7 @@ frappe.ui.form.on("Project", {
|
||||
|
||||
collect_progress: function (frm) {
|
||||
if (frm.doc.collect_progress && !frm.doc.subject) {
|
||||
frm.set_value("subject", __("For project {0}, update your status", [frm.doc.name]));
|
||||
frm.set_value("subject", __("For project - {0}, update your status", [frm.doc.project_name]));
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
@@ -12,29 +12,21 @@
|
||||
"project_name",
|
||||
"status",
|
||||
"project_type",
|
||||
"is_active",
|
||||
"percent_complete_method",
|
||||
"percent_complete",
|
||||
"column_break_5",
|
||||
"project_template",
|
||||
"expected_start_date",
|
||||
"expected_end_date",
|
||||
"priority",
|
||||
"department",
|
||||
"customer_details",
|
||||
"customer",
|
||||
"column_break_14",
|
||||
"sales_order",
|
||||
"users_section",
|
||||
"users",
|
||||
"copied_from",
|
||||
"section_break0",
|
||||
"notes",
|
||||
"is_active",
|
||||
"percent_complete",
|
||||
"section_break_18",
|
||||
"expected_start_date",
|
||||
"actual_start_date",
|
||||
"actual_time",
|
||||
"column_break_20",
|
||||
"expected_end_date",
|
||||
"actual_end_date",
|
||||
"costing_tab",
|
||||
"project_details",
|
||||
"estimated_costing",
|
||||
"total_costing_amount",
|
||||
@@ -50,7 +42,7 @@
|
||||
"gross_margin",
|
||||
"column_break_37",
|
||||
"per_gross_margin",
|
||||
"monitor_progress",
|
||||
"monitor_progress_tab",
|
||||
"collect_progress",
|
||||
"holiday_list",
|
||||
"frequency",
|
||||
@@ -63,7 +55,18 @@
|
||||
"weekly_time_to_send",
|
||||
"column_break_45",
|
||||
"subject",
|
||||
"message"
|
||||
"message",
|
||||
"more_info_tab",
|
||||
"customer_details",
|
||||
"customer",
|
||||
"column_break_14",
|
||||
"sales_order",
|
||||
"users_section",
|
||||
"users",
|
||||
"copied_from",
|
||||
"section_break0",
|
||||
"notes",
|
||||
"connections_tab"
|
||||
],
|
||||
"fields": [
|
||||
{
|
||||
@@ -231,7 +234,7 @@
|
||||
"collapsible": 1,
|
||||
"fieldname": "section_break_18",
|
||||
"fieldtype": "Section Break",
|
||||
"label": "Start and End Dates"
|
||||
"label": "Timeline"
|
||||
},
|
||||
{
|
||||
"fieldname": "actual_start_date",
|
||||
@@ -258,7 +261,6 @@
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"collapsible": 1,
|
||||
"fieldname": "project_details",
|
||||
"fieldtype": "Section Break",
|
||||
"label": "Costing and Billing",
|
||||
@@ -329,7 +331,6 @@
|
||||
"options": "Cost Center"
|
||||
},
|
||||
{
|
||||
"collapsible": 1,
|
||||
"fieldname": "margin",
|
||||
"fieldtype": "Section Break",
|
||||
"label": "Margin",
|
||||
@@ -357,12 +358,6 @@
|
||||
"oldfieldtype": "Currency",
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"collapsible": 1,
|
||||
"fieldname": "monitor_progress",
|
||||
"fieldtype": "Section Break",
|
||||
"label": "Monitor Progress"
|
||||
},
|
||||
{
|
||||
"default": "0",
|
||||
"fieldname": "collect_progress",
|
||||
@@ -455,6 +450,27 @@
|
||||
"fieldtype": "Data",
|
||||
"label": "Subject",
|
||||
"mandatory_depends_on": "collect_progress"
|
||||
},
|
||||
{
|
||||
"fieldname": "costing_tab",
|
||||
"fieldtype": "Tab Break",
|
||||
"label": "Costing"
|
||||
},
|
||||
{
|
||||
"fieldname": "monitor_progress_tab",
|
||||
"fieldtype": "Tab Break",
|
||||
"label": "Progress"
|
||||
},
|
||||
{
|
||||
"fieldname": "more_info_tab",
|
||||
"fieldtype": "Tab Break",
|
||||
"label": "More Info"
|
||||
},
|
||||
{
|
||||
"fieldname": "connections_tab",
|
||||
"fieldtype": "Tab Break",
|
||||
"label": "Connections",
|
||||
"show_dashboard": 1
|
||||
}
|
||||
],
|
||||
"icon": "fa fa-puzzle-piece",
|
||||
@@ -462,7 +478,7 @@
|
||||
"index_web_pages_for_search": 1,
|
||||
"links": [],
|
||||
"max_attachments": 4,
|
||||
"modified": "2025-08-21 17:57:58.314809",
|
||||
"modified": "2026-03-04 11:09:55.253367",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Projects",
|
||||
"name": "Project",
|
||||
|
||||
@@ -19,6 +19,13 @@ frappe.ui.form.on("Project Template", {
|
||||
frappe.ui.form.on("Project Template Task", {
|
||||
task: function (frm, cdt, cdn) {
|
||||
var row = locals[cdt][cdn];
|
||||
|
||||
if (!row.task) {
|
||||
row.subject = null;
|
||||
refresh_field("tasks");
|
||||
return;
|
||||
}
|
||||
|
||||
frappe.db.get_value("Task", row.task, "subject", (value) => {
|
||||
row.subject = value.subject;
|
||||
refresh_field("tasks");
|
||||
|
||||
@@ -13,7 +13,6 @@
|
||||
"type",
|
||||
"color",
|
||||
"is_group",
|
||||
"is_template",
|
||||
"column_break0",
|
||||
"status",
|
||||
"priority",
|
||||
@@ -21,17 +20,21 @@
|
||||
"parent_task",
|
||||
"completed_by",
|
||||
"completed_on",
|
||||
"section_break_dafi",
|
||||
"is_template",
|
||||
"column_break_vvfp",
|
||||
"start",
|
||||
"duration",
|
||||
"sb_timeline",
|
||||
"exp_start_date",
|
||||
"expected_time",
|
||||
"start",
|
||||
"column_break_11",
|
||||
"exp_end_date",
|
||||
"progress",
|
||||
"duration",
|
||||
"is_milestone",
|
||||
"sb_details",
|
||||
"description",
|
||||
"dependencies_tab",
|
||||
"sb_depends_on",
|
||||
"depends_on",
|
||||
"depends_on_tasks",
|
||||
@@ -44,12 +47,13 @@
|
||||
"total_costing_amount",
|
||||
"column_break_20",
|
||||
"total_billing_amount",
|
||||
"more_info_tab",
|
||||
"sb_more_info",
|
||||
"company",
|
||||
"review_date",
|
||||
"closing_date",
|
||||
"column_break_22",
|
||||
"department",
|
||||
"company",
|
||||
"lft",
|
||||
"rgt",
|
||||
"old_parent",
|
||||
@@ -78,7 +82,6 @@
|
||||
"oldfieldname": "project",
|
||||
"oldfieldtype": "Link",
|
||||
"options": "Project",
|
||||
"remember_last_selected_value": 1,
|
||||
"search_index": 1
|
||||
},
|
||||
{
|
||||
@@ -218,7 +221,6 @@
|
||||
{
|
||||
"fieldname": "sb_depends_on",
|
||||
"fieldtype": "Section Break",
|
||||
"label": "Dependencies",
|
||||
"oldfieldtype": "Section Break"
|
||||
},
|
||||
{
|
||||
@@ -298,10 +300,9 @@
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"collapsible": 1,
|
||||
"fieldname": "sb_more_info",
|
||||
"fieldtype": "Section Break",
|
||||
"label": "More Info"
|
||||
"label": "Additional Info"
|
||||
},
|
||||
{
|
||||
"depends_on": "eval:doc.status == \"Closed\" || doc.status == \"Pending Review\"",
|
||||
@@ -334,8 +335,7 @@
|
||||
"fieldname": "company",
|
||||
"fieldtype": "Link",
|
||||
"label": "Company",
|
||||
"options": "Company",
|
||||
"remember_last_selected_value": 1
|
||||
"options": "Company"
|
||||
},
|
||||
{
|
||||
"fieldname": "lft",
|
||||
@@ -368,6 +368,7 @@
|
||||
"options": "User"
|
||||
},
|
||||
{
|
||||
"allow_in_quick_entry": 1,
|
||||
"default": "0",
|
||||
"fieldname": "is_template",
|
||||
"fieldtype": "Check",
|
||||
@@ -397,6 +398,24 @@
|
||||
"fieldtype": "Data",
|
||||
"hidden": 1,
|
||||
"label": "Template Task"
|
||||
},
|
||||
{
|
||||
"fieldname": "dependencies_tab",
|
||||
"fieldtype": "Tab Break",
|
||||
"label": "Dependencies"
|
||||
},
|
||||
{
|
||||
"fieldname": "more_info_tab",
|
||||
"fieldtype": "Tab Break",
|
||||
"label": "More Info"
|
||||
},
|
||||
{
|
||||
"fieldname": "section_break_dafi",
|
||||
"fieldtype": "Section Break"
|
||||
},
|
||||
{
|
||||
"fieldname": "column_break_vvfp",
|
||||
"fieldtype": "Column Break"
|
||||
}
|
||||
],
|
||||
"icon": "fa fa-check",
|
||||
@@ -404,11 +423,11 @@
|
||||
"is_tree": 1,
|
||||
"links": [],
|
||||
"max_attachments": 5,
|
||||
"modified": "2025-10-16 08:39:12.214577",
|
||||
"modified": "2026-03-04 11:47:10.454548",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Projects",
|
||||
"name": "Task",
|
||||
"naming_rule": "Expression (old style)",
|
||||
"naming_rule": "Expression",
|
||||
"nsm_parent_field": "parent_task",
|
||||
"owner": "Administrator",
|
||||
"permissions": [
|
||||
@@ -425,6 +444,7 @@
|
||||
}
|
||||
],
|
||||
"quick_entry": 1,
|
||||
"row_format": "Dynamic",
|
||||
"search_fields": "subject",
|
||||
"show_name_in_global_search": 1,
|
||||
"show_preview_popup": 1,
|
||||
@@ -434,4 +454,4 @@
|
||||
"timeline_field": "project",
|
||||
"title_field": "subject",
|
||||
"track_seen": 1
|
||||
}
|
||||
}
|
||||
|
||||
@@ -138,6 +138,8 @@ class Task(NestedSet):
|
||||
def validate_status(self):
|
||||
if self.is_template and self.status != "Template":
|
||||
self.status = "Template"
|
||||
if self.status == "Template" and not self.is_template:
|
||||
self.status = "Open"
|
||||
if self.status != self.get_db_value("status") and self.status == "Completed":
|
||||
for d in self.depends_on:
|
||||
if frappe.db.get_value("Task", d.task, "status") not in ("Completed", "Cancelled"):
|
||||
|
||||
@@ -260,6 +260,33 @@ frappe.ui.form.on("Timesheet", {
|
||||
parent_project: function (frm) {
|
||||
set_project_in_timelog(frm);
|
||||
},
|
||||
|
||||
employee: function (frm) {
|
||||
if (frm.doc.employee && frm.doc.time_logs) {
|
||||
const selected_employee = frm.doc.employee;
|
||||
frm.doc.time_logs.forEach((row) => {
|
||||
if (row.activity_type) {
|
||||
frappe.call({
|
||||
method: "erpnext.projects.doctype.timesheet.timesheet.get_activity_cost",
|
||||
args: {
|
||||
employee: frm.doc.employee,
|
||||
activity_type: row.activity_type,
|
||||
currency: frm.doc.currency,
|
||||
},
|
||||
callback: function (r) {
|
||||
if (r.message) {
|
||||
if (selected_employee !== frm.doc.employee) return;
|
||||
row.billing_rate = r.message["billing_rate"];
|
||||
row.costing_rate = r.message["costing_rate"];
|
||||
frm.refresh_fields("time_logs");
|
||||
calculate_billing_costing_amount(frm, row.doctype, row.name);
|
||||
}
|
||||
},
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
frappe.ui.form.on("Timesheet Detail", {
|
||||
|
||||
@@ -18,28 +18,29 @@
|
||||
"column_break_3",
|
||||
"status",
|
||||
"parent_project",
|
||||
"employee_detail",
|
||||
"employee",
|
||||
"employee_name",
|
||||
"department",
|
||||
"column_break_9",
|
||||
"user",
|
||||
"start_date",
|
||||
"end_date",
|
||||
"employee_detail",
|
||||
"employee",
|
||||
"department",
|
||||
"column_break_9",
|
||||
"employee_name",
|
||||
"section_break_5",
|
||||
"time_logs",
|
||||
"working_hours",
|
||||
"total_hours",
|
||||
"billing_tab",
|
||||
"billing_details",
|
||||
"total_billable_hours",
|
||||
"total_billable_amount",
|
||||
"total_costing_amount",
|
||||
"base_total_billable_amount",
|
||||
"base_total_billed_amount",
|
||||
"base_total_costing_amount",
|
||||
"column_break_10",
|
||||
"total_billed_hours",
|
||||
"total_billable_amount",
|
||||
"total_billed_amount",
|
||||
"total_costing_amount",
|
||||
"base_total_billed_amount",
|
||||
"per_billed",
|
||||
"section_break_18",
|
||||
"note",
|
||||
@@ -176,7 +177,6 @@
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"collapsible": 1,
|
||||
"fieldname": "billing_details",
|
||||
"fieldtype": "Section Break",
|
||||
"label": "Billing Details",
|
||||
@@ -304,13 +304,18 @@
|
||||
"fieldname": "exchange_rate",
|
||||
"fieldtype": "Float",
|
||||
"label": "Exchange Rate"
|
||||
},
|
||||
{
|
||||
"fieldname": "billing_tab",
|
||||
"fieldtype": "Tab Break",
|
||||
"label": "Billing"
|
||||
}
|
||||
],
|
||||
"icon": "fa fa-clock-o",
|
||||
"idx": 1,
|
||||
"is_submittable": 1,
|
||||
"links": [],
|
||||
"modified": "2025-12-19 13:48:23.453636",
|
||||
"modified": "2026-03-04 11:56:51.438298",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Projects",
|
||||
"name": "Timesheet",
|
||||
|
||||
@@ -9,7 +9,7 @@ import frappe
|
||||
|
||||
@frappe.whitelist()
|
||||
@frappe.validate_and_sanitize_search_inputs
|
||||
def query_task(doctype, txt, searchfield, start, page_len, filters):
|
||||
def query_task(doctype: str, txt: str, searchfield: str, start: int, page_len: int, filters: dict):
|
||||
from frappe.desk.reportview import build_match_conditions
|
||||
|
||||
search_string = "%%%s%%" % txt
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
<svg width="54" height="54" viewBox="0 0 54 54" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M38.5714 0H15.4286C6.90761 0 0 6.90761 0 15.4286V38.5714C0 47.0924 6.90761 54 15.4286 54H38.5714C47.0924 54 54 47.0924 54 38.5714V15.4286C54 6.90761 47.0924 0 38.5714 0Z" fill="#0289F7"/>
|
||||
<path d="M19.2857 15.4286H22.1786C23.7763 15.4286 25.0714 16.7237 25.0714 18.3214V24.1071C25.0714 25.7048 23.7763 27 22.1786 27H19.2857V38.5714H15.4286V27H11.5714V23.1428H21.2143V19.2857H11.5714V15.4286H15.4286V11.5714H19.2857V15.4286ZM38.5714 38.5714H34.7143V34.7143H31.8214C30.2238 34.7143 28.9286 33.4191 28.9286 31.8214V26.0357C28.9286 24.438 30.2238 23.1428 31.8214 23.1428H34.7143V11.5714H38.5714V23.1428H42.4286V27H32.7857V30.8571H42.4286V34.7143H38.5714V38.5714Z" fill="white"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 787 B |
@@ -0,0 +1,5 @@
|
||||
|
||||
<svg width="28" height="28" viewBox="0 0 28 28" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M20 0H8C3.58172 0 0 3.58172 0 8V20C0 24.4183 3.58172 28 8 28H20C24.4183 28 28 24.4183 28 20V8C28 3.58172 24.4183 0 20 0Z" fill="#0289F7"/>
|
||||
<path d="M20.5 13.25C20.5 13.0926 20.5 13 20.5 13L18.5 11.499V19.5H20C20.2761 19.5 20 19.5 20.5 19.5V13.25ZM14.5 14V16H10.5V14H14.5ZM22.5 19C22.5 20.3807 21.3807 21.5 20 21.5H16.5V19.5V7.5C16.5 7.5 16.2761 7.5 16 7.5H9C8.72386 7.5 9 7.5 8.5 7.5V19.5C9 19.5 8.72386 19.5 9 19.5H12.5V21.5H9C7.61929 21.5 6.5 20.3807 6.5 19V8C6.5 6.61929 7.61929 5.5 9 5.5H16C17.3807 5.5 18.5 6.61929 18.5 8V9L21.5 11.25C22.1295 11.7221 22.5 12.4631 22.5 13.25V19Z" fill="white"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 713 B |
@@ -0,0 +1,4 @@
|
||||
<svg width="54" height="54" viewBox="0 0 54 54" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M38.5714 0H15.4286C6.90761 0 0 6.90761 0 15.4286V38.5714C0 47.0924 6.90761 54 15.4286 54H38.5714C47.0924 54 54 47.0924 54 38.5714V15.4286C54 6.90761 47.0924 0 38.5714 0Z" fill="#0289F7" fill-opacity="0.1"/>
|
||||
<path d="M19.2857 15.4286H22.1786C23.7762 15.4286 25.0714 16.7238 25.0714 18.3215V24.1072C25.0714 25.7049 23.7762 27 22.1786 27H19.2857V38.5715H15.4286V27H11.5714V23.1429H21.2143V19.2858H11.5714V15.4286H15.4286V11.5715H19.2857V15.4286ZM38.5714 38.5715H34.7143V34.7143H31.8214C30.2237 34.7143 28.9286 33.4192 28.9286 31.8215V26.0358C28.9286 24.4381 30.2237 23.1429 31.8214 23.1429H34.7143V11.5715H38.5714V23.1429H42.4286V27H32.7857V30.8572H42.4286V34.7143H38.5714V38.5715Z" fill="#0981E3"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 809 B |
@@ -0,0 +1,4 @@
|
||||
<svg width="28" height="28" viewBox="0 0 28 28" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M20 0H8C3.58172 0 0 3.58172 0 8V20C0 24.4183 3.58172 28 8 28H20C24.4183 28 28 24.4183 28 20V8C28 3.58172 24.4183 0 20 0Z" fill="#0289F7" fill-opacity="0.1"/>
|
||||
<path d="M20.5 13.25C20.5 13.0926 20.5 13 20.5 13L18.5 11.499V19.5H20C20.2761 19.5 20 19.5 20.5 19.5V13.25ZM14.5 14V16H10.5V14H14.5ZM22.5 19C22.5 20.3807 21.3807 21.5 20 21.5H16.5V19.5V7.5C16.5 7.5 16.2761 7.5 16 7.5H9C8.72386 7.5 9 7.5 8.5 7.5V19.5C9 19.5 8.72386 19.5 9 19.5H12.5V21.5H9C7.61929 21.5 6.5 20.3807 6.5 19V8C6.5 6.61929 7.61929 5.5 9 5.5H16C17.3807 5.5 18.5 6.61929 18.5 8V9L21.5 11.25C22.1295 11.7221 22.5 12.4631 22.5 13.25V19Z" fill="#0981E3"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 733 B |
@@ -580,6 +580,7 @@ erpnext.TransactionController = class TransactionController extends erpnext.taxe
|
||||
this.validate_has_items();
|
||||
erpnext.utils.view_serial_batch_nos(this.frm);
|
||||
this.set_route_options_for_new_doc();
|
||||
erpnext.toggle_serial_batch_fields(this.frm);
|
||||
}
|
||||
|
||||
set_route_options_for_new_doc() {
|
||||
@@ -1307,6 +1308,7 @@ erpnext.TransactionController = class TransactionController extends erpnext.taxe
|
||||
if (this.frm.doc.transaction_date) {
|
||||
this.frm.transaction_date = this.frm.doc.transaction_date;
|
||||
frappe.ui.form.trigger(this.frm.doc.doctype, "currency");
|
||||
this.recalculate_terms();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2961,6 +2963,7 @@ erpnext.TransactionController = class TransactionController extends erpnext.taxe
|
||||
frappe.call({
|
||||
method: "erpnext.controllers.stock_controller.make_quality_inspections",
|
||||
args: {
|
||||
company: me.frm.doc.company,
|
||||
doctype: me.frm.doc.doctype,
|
||||
docname: me.frm.doc.name,
|
||||
items: selected_data,
|
||||
|
||||
@@ -19,6 +19,71 @@ $.extend(erpnext, {
|
||||
return currency_list;
|
||||
},
|
||||
|
||||
toggle_serial_batch_fields(frm) {
|
||||
let hide_fields = cint(frappe.user_defaults?.enable_serial_and_batch_no_for_item) === 0 ? 1 : 0;
|
||||
let fields = ["serial_and_batch_bundle", "use_serial_batch_fields", "serial_no", "batch_no"];
|
||||
|
||||
if (
|
||||
[
|
||||
"Stock Entry",
|
||||
"Purchase Receipt",
|
||||
"Purchase Invoice",
|
||||
"Stock Reconciliation",
|
||||
"Subcontracting Receipt",
|
||||
].includes(frm.doc.doctype)
|
||||
) {
|
||||
fields.push("add_serial_batch_bundle");
|
||||
}
|
||||
|
||||
if (["Stock Reconciliation"].includes(frm.doc.doctype)) {
|
||||
fields.push("reconcile_all_serial_batch");
|
||||
}
|
||||
|
||||
if (["Sales Invoice", "Delivery Note", "Pick List"].includes(frm.doc.doctype)) {
|
||||
fields.push("pick_serial_and_batch");
|
||||
}
|
||||
|
||||
if (["Purchase Receipt", "Purchase Invoice", "Subcontracting Receipt"].includes(frm.doc.doctype)) {
|
||||
fields.push("add_serial_batch_for_rejected_qty", "rejected_serial_and_batch_bundle");
|
||||
}
|
||||
|
||||
let child_name = "items";
|
||||
if (frm.doc.doctype === "Pick List") {
|
||||
child_name = "locations";
|
||||
}
|
||||
|
||||
if (frm.doc.doctype === "Asset Capitalization") {
|
||||
child_name = "stock_items";
|
||||
}
|
||||
|
||||
fields.forEach((field) => {
|
||||
frm.fields_dict[child_name].grid.update_docfield_property(field, "hidden", hide_fields);
|
||||
|
||||
frm.fields_dict[child_name].grid.update_docfield_property(
|
||||
field,
|
||||
"in_list_view",
|
||||
hide_fields ? 0 : 1
|
||||
);
|
||||
|
||||
if (
|
||||
frm.doc.doctype === "Subcontracting Receipt" &&
|
||||
!["add_serial_batch_for_rejected_qty", "rejected_serial_and_batch_bundle"].includes(field)
|
||||
) {
|
||||
frm.fields_dict["supplied_items"].grid.update_docfield_property(field, "hidden", hide_fields);
|
||||
|
||||
frm.fields_dict["supplied_items"].grid.update_docfield_property(
|
||||
field,
|
||||
"in_list_view",
|
||||
hide_fields ? 0 : 1
|
||||
);
|
||||
|
||||
frm.fields_dict["supplied_items"].grid.reset_grid();
|
||||
}
|
||||
});
|
||||
|
||||
frm.fields_dict[child_name].grid.reset_grid();
|
||||
},
|
||||
|
||||
toggle_naming_series: function () {
|
||||
if (
|
||||
cur_frm &&
|
||||
|
||||
@@ -122,7 +122,12 @@ class QualityProcedure(NestedSet):
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_children(doctype, parent=None, parent_quality_procedure=None, is_root=False):
|
||||
def get_children(
|
||||
doctype: str,
|
||||
parent: str | None = None,
|
||||
parent_quality_procedure: str | None = None,
|
||||
is_root: bool = False,
|
||||
):
|
||||
if parent is None or parent == "All Quality Procedures":
|
||||
parent = ""
|
||||
|
||||
|
||||
@@ -31,7 +31,7 @@ def update_itemised_tax_data(doc):
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
def export_invoices(filters=None):
|
||||
def export_invoices(filters: str | None = None):
|
||||
frappe.has_permission("Sales Invoice", throw=True)
|
||||
|
||||
invoices = frappe.get_all(
|
||||
@@ -359,7 +359,7 @@ def prepare_and_attach_invoice(doc, replace=False):
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
def generate_single_invoice(docname):
|
||||
def generate_single_invoice(docname: str):
|
||||
doc = frappe.get_doc("Sales Invoice", docname)
|
||||
frappe.has_permission("Sales Invoice", doc=doc, throw=True)
|
||||
|
||||
|
||||
@@ -85,7 +85,7 @@ def get_columns():
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
def irs_1099_print(filters):
|
||||
def irs_1099_print(filters: str):
|
||||
if not filters:
|
||||
frappe._dict(
|
||||
{
|
||||
|
||||
@@ -101,7 +101,7 @@ class ProductBundle(Document):
|
||||
|
||||
@frappe.whitelist()
|
||||
@frappe.validate_and_sanitize_search_inputs
|
||||
def get_new_item_code(doctype, txt, searchfield, start, page_len, filters):
|
||||
def get_new_item_code(doctype: str, txt: str, searchfield: str, start: int, page_len: int, filters: dict):
|
||||
product_bundles = frappe.db.get_list("Product Bundle", {"disabled": 0}, pluck="name")
|
||||
|
||||
if not searchfield or searchfield == "name":
|
||||
|
||||
@@ -8,7 +8,7 @@ import frappe
|
||||
from frappe import _
|
||||
from frappe.model.document import Document
|
||||
from frappe.model.mapper import get_mapped_doc
|
||||
from frappe.utils import flt, getdate, nowdate
|
||||
from frappe.utils import cint, flt, getdate, nowdate
|
||||
|
||||
from erpnext.controllers.selling_controller import SellingController
|
||||
|
||||
@@ -451,6 +451,10 @@ def _make_sales_order(source_name, target_doc=None, ignore_permissions=False, ar
|
||||
child_filter = d.name in filtered_items if filtered_items else True
|
||||
return child_filter
|
||||
|
||||
automatically_fetch_payment_terms = cint(
|
||||
frappe.get_single_value("Accounts Settings", "automatically_fetch_payment_terms")
|
||||
)
|
||||
|
||||
doclist = get_mapped_doc(
|
||||
"Quotation",
|
||||
source_name,
|
||||
@@ -458,6 +462,7 @@ def _make_sales_order(source_name, target_doc=None, ignore_permissions=False, ar
|
||||
"Quotation": {
|
||||
"doctype": "Sales Order",
|
||||
"validation": {"docstatus": ["=", 1]},
|
||||
"field_no_map": ["payment_terms_template"],
|
||||
},
|
||||
"Quotation Item": {
|
||||
"doctype": "Sales Order Item",
|
||||
@@ -467,13 +472,15 @@ def _make_sales_order(source_name, target_doc=None, ignore_permissions=False, ar
|
||||
},
|
||||
"Sales Taxes and Charges": {"doctype": "Sales Taxes and Charges", "reset_value": True},
|
||||
"Sales Team": {"doctype": "Sales Team", "add_if_empty": True},
|
||||
"Payment Schedule": {"doctype": "Payment Schedule", "add_if_empty": True},
|
||||
},
|
||||
target_doc,
|
||||
set_missing_values,
|
||||
ignore_permissions=ignore_permissions,
|
||||
)
|
||||
|
||||
if automatically_fetch_payment_terms:
|
||||
doclist.set_payment_schedule()
|
||||
|
||||
return doclist
|
||||
|
||||
|
||||
|
||||
@@ -58,8 +58,22 @@ class TestQuotation(IntegrationTestCase):
|
||||
qo.payment_schedule[0].due_date = add_days(qo.transaction_date, -2)
|
||||
self.assertRaises(frappe.ValidationError, qo.save)
|
||||
|
||||
def test_update_child_disallow_rate_change(self):
|
||||
qo = make_quotation(qty=4)
|
||||
def test_update_child_rate_change(self):
|
||||
from erpnext.stock.doctype.item.test_item import make_item
|
||||
|
||||
item_1 = make_item("_Test Item")
|
||||
item_2 = make_item("_Test Item 1")
|
||||
|
||||
item_list = [
|
||||
{"item_code": item_1.item_code, "warehouse": "_Test Warehouse - _TC", "qty": 10, "rate": 300},
|
||||
{"item_code": item_2.item_code, "warehouse": "_Test Warehouse - _TC", "qty": 5, "rate": 400},
|
||||
]
|
||||
|
||||
qo = make_quotation(item_list=item_list)
|
||||
so = make_sales_order(qo.name, args={"filtered_children": [qo.items[0].name]})
|
||||
so.delivery_date = nowdate()
|
||||
so.submit()
|
||||
qo.reload()
|
||||
trans_item = json.dumps(
|
||||
[
|
||||
{
|
||||
@@ -67,10 +81,35 @@ class TestQuotation(IntegrationTestCase):
|
||||
"rate": 5000,
|
||||
"qty": qo.items[0].qty,
|
||||
"docname": qo.items[0].name,
|
||||
}
|
||||
},
|
||||
{
|
||||
"item_code": qo.items[1].item_code,
|
||||
"rate": qo.items[1].rate,
|
||||
"qty": qo.items[1].qty,
|
||||
"docname": qo.items[1].name,
|
||||
},
|
||||
]
|
||||
)
|
||||
self.assertRaises(frappe.ValidationError, update_child_qty_rate, "Quotation", trans_item, qo.name)
|
||||
trans_item = json.dumps(
|
||||
[
|
||||
{
|
||||
"item_code": qo.items[0].item_code,
|
||||
"rate": qo.items[0].rate,
|
||||
"qty": qo.items[0].qty,
|
||||
"docname": qo.items[0].name,
|
||||
},
|
||||
{
|
||||
"item_code": qo.items[1].item_code,
|
||||
"rate": 50,
|
||||
"qty": qo.items[1].qty,
|
||||
"docname": qo.items[1].name,
|
||||
},
|
||||
]
|
||||
)
|
||||
update_child_qty_rate("Quotation", trans_item, qo.name)
|
||||
qo.reload()
|
||||
self.assertEqual(qo.items[1].rate, 50)
|
||||
|
||||
def test_update_child_removing_item(self):
|
||||
qo = make_quotation(qty=10)
|
||||
@@ -142,6 +181,10 @@ class TestQuotation(IntegrationTestCase):
|
||||
|
||||
self.assertTrue(quotation.payment_schedule)
|
||||
|
||||
@IntegrationTestCase.change_settings(
|
||||
"Accounts Settings",
|
||||
{"automatically_fetch_payment_terms": 1},
|
||||
)
|
||||
def test_make_sales_order_terms_copied(self):
|
||||
from erpnext.selling.doctype.quotation.quotation import make_sales_order
|
||||
|
||||
@@ -284,7 +327,11 @@ class TestQuotation(IntegrationTestCase):
|
||||
|
||||
@IntegrationTestCase.change_settings(
|
||||
"Accounts Settings",
|
||||
{"add_taxes_from_item_tax_template": 0, "add_taxes_from_taxes_and_charges_template": 0},
|
||||
{
|
||||
"add_taxes_from_item_tax_template": 0,
|
||||
"add_taxes_from_taxes_and_charges_template": 0,
|
||||
"automatically_fetch_payment_terms": 1,
|
||||
},
|
||||
)
|
||||
def test_make_sales_order_with_terms(self):
|
||||
from erpnext.selling.doctype.quotation.quotation import make_sales_order
|
||||
@@ -322,10 +369,13 @@ class TestQuotation(IntegrationTestCase):
|
||||
sales_order.save()
|
||||
|
||||
self.assertEqual(sales_order.payment_schedule[0].payment_amount, 8906.00)
|
||||
self.assertEqual(sales_order.payment_schedule[0].due_date, getdate(quotation.transaction_date))
|
||||
self.assertEqual(
|
||||
getdate(sales_order.payment_schedule[0].due_date), getdate(quotation.transaction_date)
|
||||
)
|
||||
self.assertEqual(sales_order.payment_schedule[1].payment_amount, 8906.00)
|
||||
self.assertEqual(
|
||||
sales_order.payment_schedule[1].due_date, getdate(add_days(quotation.transaction_date, 30))
|
||||
getdate(sales_order.payment_schedule[1].due_date),
|
||||
getdate(add_days(quotation.transaction_date, 30)),
|
||||
)
|
||||
|
||||
def test_valid_till_before_transaction_date(self):
|
||||
@@ -1025,6 +1075,56 @@ class TestQuotation(IntegrationTestCase):
|
||||
quotation.reload()
|
||||
self.assertEqual(quotation.status, "Open")
|
||||
|
||||
@IntegrationTestCase.change_settings(
|
||||
"Accounts Settings",
|
||||
{"automatically_fetch_payment_terms": 1},
|
||||
)
|
||||
def test_make_sales_order_with_payment_terms(self):
|
||||
from erpnext.selling.doctype.quotation.quotation import make_sales_order
|
||||
|
||||
template = frappe.get_doc(
|
||||
{
|
||||
"doctype": "Payment Terms Template",
|
||||
"template_name": "_Test Payment Terms Template for Quotation",
|
||||
"terms": [
|
||||
{
|
||||
"doctype": "Payment Terms Template Detail",
|
||||
"invoice_portion": 50.00,
|
||||
"credit_days_based_on": "Day(s) after invoice date",
|
||||
"credit_days": 0,
|
||||
},
|
||||
{
|
||||
"doctype": "Payment Terms Template Detail",
|
||||
"invoice_portion": 50.00,
|
||||
"credit_days_based_on": "Day(s) after invoice date",
|
||||
"credit_days": 10,
|
||||
},
|
||||
],
|
||||
}
|
||||
).save()
|
||||
|
||||
quotation = make_quotation(qty=10, rate=1000, do_not_submit=1)
|
||||
quotation.transaction_date = add_days(nowdate(), -2)
|
||||
quotation.valid_till = add_days(nowdate(), 10)
|
||||
quotation.update({"payment_terms_template": template.name, "payment_schedule": []})
|
||||
quotation.save()
|
||||
quotation.submit()
|
||||
|
||||
self.assertEqual(quotation.payment_schedule[0].payment_amount, 5000)
|
||||
self.assertEqual(quotation.payment_schedule[1].payment_amount, 5000)
|
||||
self.assertEqual(quotation.payment_schedule[0].due_date, quotation.transaction_date)
|
||||
self.assertEqual(quotation.payment_schedule[1].due_date, add_days(quotation.transaction_date, 10))
|
||||
|
||||
sales_order = make_sales_order(quotation.name)
|
||||
sales_order.transaction_date = nowdate()
|
||||
sales_order.delivery_date = nowdate()
|
||||
sales_order.save()
|
||||
|
||||
self.assertEqual(sales_order.payment_schedule[0].due_date, sales_order.transaction_date)
|
||||
self.assertEqual(sales_order.payment_schedule[1].due_date, add_days(sales_order.transaction_date, 10))
|
||||
self.assertEqual(sales_order.payment_schedule[0].payment_amount, 5000)
|
||||
self.assertEqual(sales_order.payment_schedule[1].payment_amount, 5000)
|
||||
|
||||
|
||||
def enable_calculate_bundle_price(enable=1):
|
||||
selling_settings = frappe.get_doc("Selling Settings")
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
"column_break_7",
|
||||
"order_type",
|
||||
"transaction_date",
|
||||
"transaction_time",
|
||||
"delivery_date",
|
||||
"column_break1",
|
||||
"tax_id",
|
||||
@@ -122,6 +123,7 @@
|
||||
"company_contact_person",
|
||||
"payment_schedule_section",
|
||||
"payment_terms_section",
|
||||
"ignore_default_payment_terms_template",
|
||||
"payment_terms_template",
|
||||
"payment_schedule",
|
||||
"terms_section_break",
|
||||
@@ -1724,6 +1726,22 @@
|
||||
"fieldname": "utm_analytics_section",
|
||||
"fieldtype": "Section Break",
|
||||
"label": "UTM Analytics"
|
||||
},
|
||||
{
|
||||
"default": "Now",
|
||||
"depends_on": "is_internal_customer",
|
||||
"fieldname": "transaction_time",
|
||||
"fieldtype": "Time",
|
||||
"label": "Time",
|
||||
"mandatory_depends_on": "is_internal_customer"
|
||||
},
|
||||
{
|
||||
"default": "0",
|
||||
"fieldname": "ignore_default_payment_terms_template",
|
||||
"fieldtype": "Check",
|
||||
"hidden": 1,
|
||||
"label": "Ignore Default Payment Terms Template",
|
||||
"read_only": 1
|
||||
}
|
||||
],
|
||||
"grid_page_length": 50,
|
||||
@@ -1731,7 +1749,7 @@
|
||||
"idx": 105,
|
||||
"is_submittable": 1,
|
||||
"links": [],
|
||||
"modified": "2026-02-23 13:25:56.665392",
|
||||
"modified": "2026-03-04 18:04:05.873483",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Selling",
|
||||
"name": "Sales Order",
|
||||
|
||||
@@ -117,6 +117,7 @@ class SalesOrder(SellingController):
|
||||
grand_total: DF.Currency
|
||||
group_same_items: DF.Check
|
||||
has_unit_price_items: DF.Check
|
||||
ignore_default_payment_terms_template: DF.Check
|
||||
ignore_pricing_rule: DF.Check
|
||||
in_words: DF.Data | None
|
||||
incoterm: DF.Link | None
|
||||
@@ -187,6 +188,7 @@ class SalesOrder(SellingController):
|
||||
total_qty: DF.Float
|
||||
total_taxes_and_charges: DF.Currency
|
||||
transaction_date: DF.Date
|
||||
transaction_time: DF.Time | None
|
||||
utm_campaign: DF.Link | None
|
||||
utm_content: DF.Data | None
|
||||
utm_medium: DF.Link | None
|
||||
@@ -1610,12 +1612,14 @@ def make_purchase_order(
|
||||
|
||||
def set_missing_values(source, target):
|
||||
target.supplier = supplier
|
||||
target.currency = frappe.db.get_value(
|
||||
"Supplier", filters={"name": supplier}, fieldname=["default_currency"]
|
||||
)
|
||||
company_currency = frappe.db.get_value(
|
||||
"Company", filters={"name": target.company}, fieldname=["default_currency"]
|
||||
)
|
||||
supplier_currency = frappe.db.get_value(
|
||||
"Supplier", filters={"name": supplier}, fieldname=["default_currency"]
|
||||
)
|
||||
|
||||
target.currency = supplier_currency if supplier_currency else company_currency
|
||||
|
||||
target.conversion_rate = get_exchange_rate(target.currency, company_currency, args="for_buying")
|
||||
|
||||
|
||||
@@ -2647,6 +2647,49 @@ class TestSalesOrder(AccountsTestMixin, IntegrationTestCase):
|
||||
si2 = make_sales_invoice(so.name)
|
||||
self.assertEqual(si2.items[0].qty, 20)
|
||||
|
||||
@change_settings("Selling Settings", {"validate_selling_price": 1})
|
||||
def test_selling_price_validation_for_manufactured_item(self):
|
||||
"""
|
||||
Unit test to check the selling price validation for manufactured item, without last purchae rate in Item master.
|
||||
"""
|
||||
|
||||
from erpnext.manufacturing.doctype.production_plan.test_production_plan import make_bom
|
||||
from erpnext.stock.doctype.warehouse.test_warehouse import create_warehouse
|
||||
|
||||
# create a FG Item and RM Item
|
||||
rm_item = make_item(
|
||||
"_Test RM Item for SO selling validation",
|
||||
{"is_stock_item": 1, "valuation_rate": 100, "stock_uom": "Nos"},
|
||||
).name
|
||||
rm_warehouse = create_warehouse("_Test RM SPV Warehouse")
|
||||
fg_item = make_item("_Test FG Item for SO selling validation", {"is_stock_item": 1}).name
|
||||
fg_warehouse = create_warehouse("_Test FG SPV Warehouse")
|
||||
|
||||
# create BOM and inward entry for RM Item
|
||||
bom_no = make_bom(item=fg_item, raw_materials=[rm_item]).name
|
||||
make_stock_entry(item_code=rm_item, target=rm_warehouse, qty=10, rate=100)
|
||||
|
||||
# create a manufacture entry, so system won't update the last purchase rate in Item master.
|
||||
se = make_stock_entry(item_code=fg_item, qty=10, purpose="Manufacture", do_not_save=True)
|
||||
|
||||
se.from_bom = 1
|
||||
se.use_multi_level_bom = 1
|
||||
se.bom_no = bom_no
|
||||
se.fg_completed_qty = 1
|
||||
se.from_warehouse = rm_warehouse
|
||||
se.to_warehouse = fg_warehouse
|
||||
|
||||
se.get_items()
|
||||
se.save()
|
||||
se.submit()
|
||||
|
||||
# check valuation of FG Item
|
||||
self.assertEqual(se.items[1].valuation_rate, 100)
|
||||
|
||||
# create a SO for FG Item with selling rate than valuation rate.
|
||||
so = make_sales_order(item_code=fg_item, qty=10, rate=50, warehouse=fg_warehouse, do_not_save=1)
|
||||
self.assertRaises(frappe.ValidationError, so.save)
|
||||
|
||||
|
||||
def compare_payment_schedules(doc, doc1, doc2):
|
||||
for index, schedule in enumerate(doc1.get("payment_schedule")):
|
||||
|
||||
@@ -95,6 +95,7 @@
|
||||
"ordered_qty",
|
||||
"planned_qty",
|
||||
"production_plan_qty",
|
||||
"requested_qty",
|
||||
"column_break_69",
|
||||
"work_order_qty",
|
||||
"delivered_qty",
|
||||
@@ -1010,6 +1011,14 @@
|
||||
"fieldtype": "Float",
|
||||
"label": "Finished Good Qty",
|
||||
"mandatory_depends_on": "eval:parent.is_subcontracted"
|
||||
},
|
||||
{
|
||||
"fieldname": "requested_qty",
|
||||
"fieldtype": "Float",
|
||||
"label": "Requested Qty",
|
||||
"no_copy": 1,
|
||||
"print_hide": 1,
|
||||
"read_only": 1
|
||||
}
|
||||
],
|
||||
"grid_page_length": 50,
|
||||
|
||||
@@ -80,6 +80,7 @@ class SalesOrderItem(Document):
|
||||
quotation_item: DF.Data | None
|
||||
rate: DF.Currency
|
||||
rate_with_margin: DF.Currency
|
||||
requested_qty: DF.Float
|
||||
reserve_stock: DF.Check
|
||||
returned_qty: DF.Float
|
||||
stock_qty: DF.Float
|
||||
|
||||
@@ -329,7 +329,7 @@
|
||||
"index_web_pages_for_search": 1,
|
||||
"issingle": 1,
|
||||
"links": [],
|
||||
"modified": "2026-02-12 10:38:34.605126",
|
||||
"modified": "2026-02-27 00:47:46.003305",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Selling",
|
||||
"name": "Selling Settings",
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
|
||||
|
||||
import json
|
||||
from typing import Literal
|
||||
|
||||
import frappe
|
||||
import frappe.defaults
|
||||
@@ -938,7 +939,7 @@ def cache_companies_monthly_sales_history():
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_children(doctype, parent=None, company=None, is_root=False):
|
||||
def get_children(doctype: str, parent: str | None = None, company: str | None = None, is_root: bool = False):
|
||||
if parent is None or parent == "All Companies":
|
||||
parent = ""
|
||||
|
||||
@@ -1045,10 +1046,11 @@ def get_timeline_data(doctype, name):
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_default_company_address(name, sort_key="is_primary_address", existing_address=None):
|
||||
if sort_key not in ["is_shipping_address", "is_primary_address"]:
|
||||
return None
|
||||
|
||||
def get_default_company_address(
|
||||
name: str,
|
||||
sort_key: Literal["is_shipping_address", "is_primary_address"] = "is_primary_address",
|
||||
existing_address: str | None = None,
|
||||
):
|
||||
out = frappe.db.sql(
|
||||
""" SELECT
|
||||
addr.name, addr.{}
|
||||
@@ -1072,7 +1074,9 @@ def get_default_company_address(name, sort_key="is_primary_address", existing_ad
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_billing_shipping_address(name, billing_address=None, shipping_address=None):
|
||||
def get_billing_shipping_address(
|
||||
name: str, billing_address: str | None = None, shipping_address: str | None = None
|
||||
):
|
||||
primary_address = get_default_company_address(name, "is_primary_address", billing_address)
|
||||
shipping_address = get_default_company_address(name, "is_shipping_address", shipping_address)
|
||||
|
||||
@@ -1080,7 +1084,7 @@ def get_billing_shipping_address(name, billing_address=None, shipping_address=No
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
def create_transaction_deletion_request(company):
|
||||
def create_transaction_deletion_request(company: str):
|
||||
frappe.only_for("System Manager")
|
||||
|
||||
from erpnext.setup.doctype.transaction_deletion_record.transaction_deletion_record import (
|
||||
|
||||
@@ -70,7 +70,13 @@ def get_abbreviated_name(name, company):
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_children(doctype, parent=None, company=None, is_root=False, include_disabled=False):
|
||||
def get_children(
|
||||
doctype: str,
|
||||
parent: str | None = None,
|
||||
company: str | None = None,
|
||||
is_root: bool = False,
|
||||
include_disabled: str | dict | None = None,
|
||||
):
|
||||
if isinstance(include_disabled, str):
|
||||
include_disabled = json.loads(include_disabled)
|
||||
fields = ["name as value", "is_group as expandable"]
|
||||
|
||||
@@ -900,7 +900,7 @@ def send():
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_digest_msg(name):
|
||||
def get_digest_msg(name: str):
|
||||
return frappe.get_doc("Email Digest", name).get_msg_html()
|
||||
|
||||
|
||||
|
||||
@@ -410,7 +410,7 @@ def is_holiday(employee, date=None, raise_exception=True, only_non_weekly=False,
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
def deactivate_sales_person(status=None, employee=None):
|
||||
def deactivate_sales_person(status: str | None = None, employee: str | None = None):
|
||||
if status == "Left":
|
||||
sales_person = frappe.db.get_value("Sales Person", {"Employee": employee})
|
||||
if sales_person:
|
||||
@@ -519,7 +519,13 @@ def get_employee_emails(employee_list):
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_children(doctype, parent=None, company=None, is_root=False, is_tree=False):
|
||||
def get_children(
|
||||
doctype: str,
|
||||
parent: str | None = None,
|
||||
company: str | None = None,
|
||||
is_root: bool = False,
|
||||
is_tree: bool = False,
|
||||
):
|
||||
filters = [["status", "=", "Active"]]
|
||||
if company and company != "All Companies":
|
||||
filters.append(["company", "=", company])
|
||||
|
||||
@@ -8,7 +8,7 @@ from datetime import date
|
||||
import frappe
|
||||
from frappe import _, throw
|
||||
from frappe.model.document import Document
|
||||
from frappe.utils import formatdate, getdate, today
|
||||
from frappe.utils import DateTimeLikeObject, formatdate, getdate, today
|
||||
|
||||
|
||||
class OverlapError(frappe.ValidationError):
|
||||
@@ -168,7 +168,7 @@ class HolidayList(Document):
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_events(start, end, filters=None):
|
||||
def get_events(start: DateTimeLikeObject, end: DateTimeLikeObject, filters: str | dict | None = None):
|
||||
"""Returns events for Gantt / Calendar view rendering.
|
||||
|
||||
:param start: Start date-time.
|
||||
|
||||
@@ -24,7 +24,7 @@ class PartyType(Document):
|
||||
|
||||
@frappe.whitelist()
|
||||
@frappe.validate_and_sanitize_search_inputs
|
||||
def get_party_type(doctype, txt, searchfield, start, page_len, filters):
|
||||
def get_party_type(doctype: str, txt: str, searchfield: str, start: int, page_len: int, filters: dict):
|
||||
cond = ""
|
||||
account_type = None
|
||||
|
||||
|
||||
@@ -35,7 +35,7 @@ class TermsandConditions(Document):
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_terms_and_conditions(template_name, doc):
|
||||
def get_terms_and_conditions(template_name: str, doc: str | dict):
|
||||
if isinstance(doc, str):
|
||||
doc = json.loads(doc)
|
||||
|
||||
|
||||
@@ -75,7 +75,7 @@ def get_protected_doctypes():
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_company_link_fields(doctype_name):
|
||||
def get_company_link_fields(doctype_name: str):
|
||||
"""Get all Company Link field names for a DocType (whitelisted for frontend autocomplete)
|
||||
|
||||
Args:
|
||||
@@ -428,7 +428,9 @@ class TransactionDeletionRecord(Document):
|
||||
return {"count": len(self.doctypes_to_delete)}
|
||||
|
||||
@frappe.whitelist()
|
||||
def populate_doctype_details(self, doctype_name, company=None, company_field=None):
|
||||
def populate_doctype_details(
|
||||
self, doctype_name: str, company: str | None = None, company_field: str | None = None
|
||||
):
|
||||
"""Get child DocTypes and document count for specified DocType
|
||||
|
||||
Args:
|
||||
@@ -1035,7 +1037,7 @@ def get_doctypes_to_be_ignored():
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
def export_to_delete_template(name):
|
||||
def export_to_delete_template(name: str):
|
||||
"""Export To Delete list as CSV via URL access"""
|
||||
frappe.only_for("System Manager")
|
||||
doc = frappe.get_doc("Transaction Deletion Record", name)
|
||||
@@ -1044,7 +1046,7 @@ def export_to_delete_template(name):
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
def process_import_template(transaction_deletion_record_name, file_url):
|
||||
def process_import_template(transaction_deletion_record_name: str, file_url: str):
|
||||
"""Import CSV template and populate To Delete list"""
|
||||
import os
|
||||
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
{
|
||||
"allow_roles": [
|
||||
{
|
||||
"role": "System Manager"
|
||||
},
|
||||
{
|
||||
"role": "Sales Manager"
|
||||
},
|
||||
{
|
||||
"role": "Accounts Manager"
|
||||
},
|
||||
{
|
||||
"role": "Manufacturing Manager"
|
||||
},
|
||||
{
|
||||
"role": "Stock Manager"
|
||||
}
|
||||
],
|
||||
"creation": "2026-02-24 18:03:53.158438",
|
||||
"docstatus": 0,
|
||||
"doctype": "Module Onboarding",
|
||||
"idx": 0,
|
||||
"is_complete": 0,
|
||||
"modified": "2026-02-24 18:07:36.808560",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Setup",
|
||||
"name": "Organization Onboarding",
|
||||
"owner": "Administrator",
|
||||
"steps": [
|
||||
{
|
||||
"step": "Setup Company"
|
||||
},
|
||||
{
|
||||
"step": "Invite Users"
|
||||
},
|
||||
{
|
||||
"step": "Setup Email Account"
|
||||
},
|
||||
{
|
||||
"step": "Setup Role Permissions"
|
||||
},
|
||||
{
|
||||
"step": "Review System Settings"
|
||||
}
|
||||
],
|
||||
"title": "Setup Organization"
|
||||
}
|
||||
20
erpnext/setup/onboarding_step/invite_users/invite_users.json
Normal file
20
erpnext/setup/onboarding_step/invite_users/invite_users.json
Normal file
@@ -0,0 +1,20 @@
|
||||
{
|
||||
"action": "Create Entry",
|
||||
"action_label": "Invite Users",
|
||||
"creation": "2026-02-24 18:04:21.585575",
|
||||
"docstatus": 0,
|
||||
"doctype": "Onboarding Step",
|
||||
"idx": 0,
|
||||
"is_complete": 0,
|
||||
"is_single": 0,
|
||||
"is_skipped": 0,
|
||||
"modified": "2026-02-24 18:04:21.585575",
|
||||
"modified_by": "Administrator",
|
||||
"name": "Invite Users",
|
||||
"owner": "Administrator",
|
||||
"reference_document": "User",
|
||||
"show_form_tour": 0,
|
||||
"show_full_form": 0,
|
||||
"title": "Invite Users",
|
||||
"validate_action": 1
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
{
|
||||
"action": "Update Settings",
|
||||
"action_label": "Review System Settings",
|
||||
"creation": "2026-02-24 18:06:56.781335",
|
||||
"docstatus": 0,
|
||||
"doctype": "Onboarding Step",
|
||||
"idx": 0,
|
||||
"is_complete": 0,
|
||||
"is_single": 1,
|
||||
"is_skipped": 0,
|
||||
"modified": "2026-02-24 18:06:56.781335",
|
||||
"modified_by": "Administrator",
|
||||
"name": "Review System Settings",
|
||||
"owner": "Administrator",
|
||||
"reference_document": "System Settings",
|
||||
"show_form_tour": 0,
|
||||
"show_full_form": 0,
|
||||
"title": "Review System Settings",
|
||||
"validate_action": 0,
|
||||
"value_to_validate": ""
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
{
|
||||
"action": "Go to Page",
|
||||
"action_label": "Setup Company",
|
||||
"creation": "2026-02-20 11:12:50.373049",
|
||||
"docstatus": 0,
|
||||
"doctype": "Onboarding Step",
|
||||
"idx": 1,
|
||||
"is_complete": 0,
|
||||
"is_single": 0,
|
||||
"is_skipped": 0,
|
||||
"modified": "2026-02-23 21:10:17.680053",
|
||||
"modified_by": "Administrator",
|
||||
"name": "Setup Company",
|
||||
"owner": "Administrator",
|
||||
"path": "company",
|
||||
"reference_document": "Company",
|
||||
"show_form_tour": 0,
|
||||
"show_full_form": 0,
|
||||
"title": "Setup Company",
|
||||
"validate_action": 1
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
{
|
||||
"action": "Create Entry",
|
||||
"action_label": "Setup Email Account",
|
||||
"creation": "2026-02-24 18:04:39.983155",
|
||||
"docstatus": 0,
|
||||
"doctype": "Onboarding Step",
|
||||
"idx": 0,
|
||||
"is_complete": 0,
|
||||
"is_single": 0,
|
||||
"is_skipped": 0,
|
||||
"modified": "2026-02-24 18:04:39.983155",
|
||||
"modified_by": "Administrator",
|
||||
"name": "Setup Email Account",
|
||||
"owner": "Administrator",
|
||||
"reference_document": "Email Account",
|
||||
"show_form_tour": 0,
|
||||
"show_full_form": 0,
|
||||
"title": "Setup Email Account",
|
||||
"validate_action": 1
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
{
|
||||
"action": "Go to Page",
|
||||
"action_label": "Setup Role Permissions",
|
||||
"creation": "2026-02-24 18:05:10.485778",
|
||||
"docstatus": 0,
|
||||
"doctype": "Onboarding Step",
|
||||
"idx": 0,
|
||||
"is_complete": 0,
|
||||
"is_single": 0,
|
||||
"is_skipped": 0,
|
||||
"modified": "2026-02-24 18:05:10.485778",
|
||||
"modified_by": "Administrator",
|
||||
"name": "Setup Role Permissions",
|
||||
"owner": "Administrator",
|
||||
"path": "permission-manager",
|
||||
"show_form_tour": 0,
|
||||
"show_full_form": 0,
|
||||
"title": "Setup Role Permissions",
|
||||
"validate_action": 1
|
||||
}
|
||||
@@ -4,7 +4,7 @@
|
||||
import frappe
|
||||
from frappe import _
|
||||
from frappe.utils import add_days, flt, get_datetime_str, nowdate
|
||||
from frappe.utils.data import now_datetime
|
||||
from frappe.utils.data import DateTimeLikeObject, now_datetime
|
||||
from frappe.utils.nestedset import get_root_of
|
||||
|
||||
from erpnext import get_default_company
|
||||
@@ -92,7 +92,12 @@ def get_pegged_rate(pegged_map, from_currency, to_currency, transaction_date=Non
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_exchange_rate(from_currency, to_currency, transaction_date=None, args=None):
|
||||
def get_exchange_rate(
|
||||
from_currency: str,
|
||||
to_currency: str,
|
||||
transaction_date: DateTimeLikeObject | None = None,
|
||||
args: str | None = None,
|
||||
):
|
||||
if not (from_currency and to_currency):
|
||||
# manqala 19/09/2016: Should this be an empty return or should it throw and exception?
|
||||
return
|
||||
@@ -221,6 +226,8 @@ def set_defaults_for_tests():
|
||||
frappe.db.set_default(key, value)
|
||||
frappe.db.set_single_value("Stock Settings", "auto_insert_price_list_rate_if_missing", 0)
|
||||
|
||||
frappe.db.set_single_value("Stock Settings", "enable_serial_and_batch_no_for_item", 1)
|
||||
|
||||
|
||||
def insert_record(records):
|
||||
from frappe.desk.page.setup_wizard.setup_wizard import make_records
|
||||
|
||||
@@ -54,7 +54,7 @@ def get_leaderboards():
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_all_customers(date_range, company, field, limit=None):
|
||||
def get_all_customers(date_range: str, company: str, field: str, limit: int | None = None):
|
||||
filters = [["docstatus", "=", "1"], ["company", "=", company]]
|
||||
from_date, to_date = parse_date_range(date_range)
|
||||
if field == "outstanding_amount":
|
||||
@@ -89,7 +89,7 @@ def get_all_customers(date_range, company, field, limit=None):
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_all_items(date_range, company, field, limit=None):
|
||||
def get_all_items(date_range: str, company: str, field: str, limit: int | None = None):
|
||||
if field in ("available_stock_qty", "available_stock_value"):
|
||||
sum_field = "actual_qty" if field == "available_stock_qty" else "stock_value"
|
||||
results = frappe.db.get_all(
|
||||
@@ -135,7 +135,7 @@ def get_all_items(date_range, company, field, limit=None):
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_all_suppliers(date_range, company, field, limit=None):
|
||||
def get_all_suppliers(date_range: str, company: str, field: str, limit: int | None = None):
|
||||
filters = [["docstatus", "=", "1"], ["company", "=", company]]
|
||||
from_date, to_date = parse_date_range(date_range)
|
||||
|
||||
@@ -171,7 +171,7 @@ def get_all_suppliers(date_range, company, field, limit=None):
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_all_sales_partner(date_range, company, field, limit=None):
|
||||
def get_all_sales_partner(date_range: str, company: str, field: str, limit: int | None = None):
|
||||
if field == "total_sales_amount":
|
||||
select_field = "base_net_total"
|
||||
elif field == "total_commission":
|
||||
@@ -196,7 +196,7 @@ def get_all_sales_partner(date_range, company, field, limit=None):
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_all_sales_person(date_range, company, field=None, limit=0):
|
||||
def get_all_sales_person(date_range: str, company: str, field: str | None = None, limit: int | None = None):
|
||||
filters = [
|
||||
["docstatus", "=", "1"],
|
||||
["company", "=", company],
|
||||
|
||||
@@ -84,7 +84,25 @@ frappe.ui.form.on("Item", {
|
||||
}
|
||||
},
|
||||
|
||||
toggle_has_serial_batch_fields(frm) {
|
||||
let hide_fields = cint(frappe.user_defaults?.enable_serial_and_batch_no_for_item) === 0 ? 1 : 0;
|
||||
|
||||
frm.toggle_display(["serial_no_series", "batch_number_series", "create_new_batch"], !hide_fields);
|
||||
frm.toggle_enable(["has_serial_no", "has_batch_no"], !hide_fields);
|
||||
|
||||
if (hide_fields) {
|
||||
let description = __(
|
||||
"To enable the Serial No and Batch No feature, please check the 'Enable Serial / Batch No for Item' checkbox in Stock Settings."
|
||||
);
|
||||
|
||||
frm.set_df_property("has_serial_no", "description", description);
|
||||
frm.set_df_property("has_batch_no", "description", description);
|
||||
}
|
||||
},
|
||||
|
||||
refresh: function (frm) {
|
||||
frm.trigger("toggle_has_serial_batch_fields");
|
||||
|
||||
if (frm.doc.is_stock_item) {
|
||||
frm.add_custom_button(
|
||||
__("Stock Balance"),
|
||||
|
||||
@@ -452,6 +452,7 @@
|
||||
"fieldname": "batch_number_series",
|
||||
"fieldtype": "Data",
|
||||
"label": "Batch Number Series",
|
||||
"show_description_on_click": 1,
|
||||
"translatable": 1
|
||||
},
|
||||
{
|
||||
@@ -493,7 +494,8 @@
|
||||
"description": "Example: ABCD.#####\nIf series is set and Serial No is not mentioned in transactions, then automatic serial number will be created based on this series. If you always want to explicitly mention Serial Nos for this item. leave this blank.",
|
||||
"fieldname": "serial_no_series",
|
||||
"fieldtype": "Data",
|
||||
"label": "Serial Number Series"
|
||||
"label": "Serial Number Series",
|
||||
"show_description_on_click": 1
|
||||
},
|
||||
{
|
||||
"collapsible": 1,
|
||||
@@ -985,7 +987,7 @@
|
||||
"image_field": "image",
|
||||
"links": [],
|
||||
"make_attachments_public": 1,
|
||||
"modified": "2026-02-05 17:20:35.605734",
|
||||
"modified": "2026-03-05 16:29:31.653447",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Stock",
|
||||
"name": "Item",
|
||||
|
||||
@@ -16,6 +16,10 @@ from erpnext.controllers.taxes_and_totals import init_landed_taxes_and_totals
|
||||
from erpnext.stock.doctype.serial_no.serial_no import get_serial_nos
|
||||
|
||||
|
||||
class IncorrectCompanyValidationError(frappe.ValidationError):
|
||||
pass
|
||||
|
||||
|
||||
class LandedCostVoucher(Document):
|
||||
# begin: auto-generated types
|
||||
# This code is auto-generated. Do not modify anything in this block.
|
||||
@@ -77,6 +81,7 @@ class LandedCostVoucher(Document):
|
||||
self.check_mandatory()
|
||||
self.validate_receipt_documents()
|
||||
self.validate_line_items()
|
||||
self.validate_expense_accounts()
|
||||
init_landed_taxes_and_totals(self)
|
||||
self.set_total_taxes_and_charges()
|
||||
if not self.get("items"):
|
||||
@@ -118,11 +123,28 @@ class LandedCostVoucher(Document):
|
||||
receipt_documents = []
|
||||
|
||||
for d in self.get("purchase_receipts"):
|
||||
docstatus = frappe.db.get_value(d.receipt_document_type, d.receipt_document, "docstatus")
|
||||
docstatus, company = frappe.get_cached_value(
|
||||
d.receipt_document_type, d.receipt_document, ["docstatus", "company"]
|
||||
)
|
||||
if docstatus != 1:
|
||||
msg = f"Row {d.idx}: {d.receipt_document_type} {frappe.bold(d.receipt_document)} must be submitted"
|
||||
frappe.throw(_(msg), title=_("Invalid Document"))
|
||||
|
||||
if company != self.company:
|
||||
frappe.throw(
|
||||
_(
|
||||
"Row {0}: {1} {2} is linked to company {3}. Please select a document belonging to company {4}."
|
||||
).format(
|
||||
d.idx,
|
||||
d.receipt_document_type,
|
||||
frappe.bold(d.receipt_document),
|
||||
frappe.bold(company),
|
||||
frappe.bold(self.company),
|
||||
),
|
||||
title=_("Incorrect Company"),
|
||||
exc=IncorrectCompanyValidationError,
|
||||
)
|
||||
|
||||
if d.receipt_document_type == "Purchase Invoice":
|
||||
update_stock = frappe.db.get_value(
|
||||
d.receipt_document_type, d.receipt_document, "update_stock"
|
||||
@@ -154,6 +176,24 @@ class LandedCostVoucher(Document):
|
||||
_("Row {0}: Cost center is required for an item {1}").format(item.idx, item.item_code)
|
||||
)
|
||||
|
||||
def validate_expense_accounts(self):
|
||||
for t in self.taxes:
|
||||
company = frappe.get_cached_value("Account", t.expense_account, "company")
|
||||
|
||||
if company != self.company:
|
||||
frappe.throw(
|
||||
_(
|
||||
"Row {0}: Expense Account {1} is linked to company {2}. Please select an account belonging to company {3}."
|
||||
).format(
|
||||
t.idx,
|
||||
frappe.bold(t.expense_account),
|
||||
frappe.bold(company),
|
||||
frappe.bold(self.company),
|
||||
),
|
||||
title=_("Incorrect Account"),
|
||||
exc=IncorrectCompanyValidationError,
|
||||
)
|
||||
|
||||
def set_total_taxes_and_charges(self):
|
||||
self.total_taxes_and_charges = sum(flt(d.base_amount) for d in self.get("taxes"))
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user