mirror of
https://github.com/frappe/erpnext.git
synced 2026-08-07 03:33:03 +00:00
Compare commits
10 Commits
l10n_versi
...
v16.31.0
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
68ea583a1f | ||
|
|
2769a8c69e | ||
|
|
8378b6e203 | ||
|
|
eaf95e5c36 | ||
|
|
a5de60c357 | ||
|
|
264bfa188b | ||
|
|
de591661b9 | ||
|
|
9a7e796fd2 | ||
|
|
9d5c7605b8 | ||
|
|
f94eee3197 |
@@ -6,7 +6,7 @@ import frappe
|
||||
from frappe.model.document import Document
|
||||
from frappe.utils.user import is_website_user
|
||||
|
||||
__version__ = "16.26.2"
|
||||
__version__ = "16.31.0"
|
||||
|
||||
|
||||
def get_default_company(user=None):
|
||||
|
||||
@@ -6,10 +6,9 @@ import copy
|
||||
|
||||
import frappe
|
||||
from frappe import _
|
||||
from frappe.query_builder.functions import Max, Sum
|
||||
from frappe.utils import add_days, flt, fmt_money, formatdate, get_link_to_form, getdate
|
||||
from frappe.query_builder.functions import Sum
|
||||
from frappe.utils import add_days, flt, formatdate, getdate
|
||||
|
||||
from erpnext import is_perpetual_inventory_enabled
|
||||
from erpnext.accounts.doctype.account_closing_balance.account_closing_balance import (
|
||||
make_closing_entries,
|
||||
)
|
||||
@@ -19,8 +18,6 @@ from erpnext.accounts.doctype.accounting_dimension.accounting_dimension import (
|
||||
from erpnext.accounts.general_ledger import check_freezing_date, is_immutable_ledger_enabled
|
||||
from erpnext.accounts.utils import get_account_currency, get_fiscal_year
|
||||
from erpnext.controllers.accounts_controller import AccountsController
|
||||
from erpnext.stock.doctype.stock_closing_entry.stock_closing_entry import apply_unscoped_filters
|
||||
from erpnext.stock.utils import get_stock_value_on
|
||||
|
||||
|
||||
class PeriodClosingVoucher(AccountsController):
|
||||
@@ -142,121 +139,6 @@ class PeriodClosingVoucher(AccountsController):
|
||||
if account_currency != company_currency:
|
||||
frappe.throw(_("Currency of the Closing Account must be {0}").format(company_currency))
|
||||
|
||||
def before_submit(self):
|
||||
if not self.has_stock_transactions():
|
||||
return
|
||||
|
||||
self.validate_stock_accounts_balance()
|
||||
self.validate_stock_closing_entry()
|
||||
|
||||
def has_stock_transactions(self):
|
||||
if not is_perpetual_inventory_enabled(self.company):
|
||||
return False
|
||||
|
||||
return bool(
|
||||
frappe.db.exists(
|
||||
"Stock Ledger Entry",
|
||||
{
|
||||
"company": self.company,
|
||||
"is_cancelled": 0,
|
||||
"posting_date": ("<=", self.period_end_date),
|
||||
},
|
||||
)
|
||||
)
|
||||
|
||||
def validate_stock_accounts_balance(self):
|
||||
precision = frappe.get_precision("GL Entry", "debit")
|
||||
account_balance = flt(self.get_stock_accounts_balance(), precision)
|
||||
stock_value = flt(
|
||||
get_stock_value_on(posting_date=self.period_end_date, company=self.company), precision
|
||||
)
|
||||
|
||||
if account_balance == stock_value:
|
||||
return
|
||||
|
||||
currency = frappe.get_cached_value("Company", self.company, "default_currency")
|
||||
frappe.throw(
|
||||
_(
|
||||
"The closing balance {0} of the Stock Asset accounts does not match the closing value {1} of the Stock Balance report as on {2}. Resolve the difference using the Stock Ledger Variance report before closing the period."
|
||||
).format(
|
||||
frappe.bold(fmt_money(account_balance, currency=currency)),
|
||||
frappe.bold(fmt_money(stock_value, currency=currency)),
|
||||
frappe.bold(formatdate(self.period_end_date)),
|
||||
),
|
||||
title=_("Stock Value Mismatch"),
|
||||
)
|
||||
|
||||
def get_stock_accounts_balance(self):
|
||||
gle = frappe.qb.DocType("GL Entry")
|
||||
account = frappe.qb.DocType("Account")
|
||||
|
||||
stock_accounts = (
|
||||
frappe.qb.from_(account)
|
||||
.select(account.name)
|
||||
.where(
|
||||
(account.account_type == "Stock")
|
||||
& (account.company == self.company)
|
||||
& (account.is_group == 0)
|
||||
)
|
||||
)
|
||||
|
||||
balance = (
|
||||
frappe.qb.from_(gle)
|
||||
.select(Sum(gle.debit - gle.credit))
|
||||
.where(
|
||||
(gle.company == self.company)
|
||||
& (gle.is_cancelled == 0)
|
||||
& (gle.posting_date <= self.period_end_date)
|
||||
& gle.account.isin(stock_accounts)
|
||||
)
|
||||
).run()
|
||||
|
||||
return flt(balance[0][0]) if balance else 0.0
|
||||
|
||||
def validate_stock_closing_entry(self):
|
||||
closing_entry = frappe.db.get_value(
|
||||
"Stock Closing Entry",
|
||||
apply_unscoped_filters(
|
||||
{"company": self.company, "to_date": self.period_end_date, "docstatus": 1}
|
||||
),
|
||||
["name", "status", "modified"],
|
||||
as_dict=True,
|
||||
)
|
||||
|
||||
if not closing_entry:
|
||||
frappe.throw(
|
||||
_(
|
||||
"Create a Stock Closing Entry for the entire company with To Date as {0} before submitting the Period Closing Voucher."
|
||||
).format(frappe.bold(formatdate(self.period_end_date))),
|
||||
title=_("Stock Closing Entry Required"),
|
||||
)
|
||||
|
||||
if closing_entry.status != "Completed":
|
||||
frappe.throw(
|
||||
_(
|
||||
"The Stock Closing Entry for {0} is not completed yet. Wait for it to complete before submitting the Period Closing Voucher."
|
||||
).format(frappe.bold(formatdate(self.period_end_date))),
|
||||
title=_("Stock Closing Entry In Progress"),
|
||||
)
|
||||
|
||||
self.validate_stock_closing_entry_is_fresh(closing_entry)
|
||||
|
||||
def validate_stock_closing_entry_is_fresh(self, closing_entry):
|
||||
sle = frappe.qb.DocType("Stock Ledger Entry")
|
||||
last_change = (
|
||||
frappe.qb.from_(sle)
|
||||
.select(Max(sle.modified))
|
||||
.where((sle.company == self.company) & (sle.posting_date <= self.period_end_date))
|
||||
).run()
|
||||
|
||||
if last_change and last_change[0][0] and last_change[0][0] > closing_entry.modified:
|
||||
frappe.throw(
|
||||
_(
|
||||
"Stock transactions were created or modified after the Stock Closing Entry {0} was generated. Regenerate it before submitting the Period Closing Voucher."
|
||||
).format(get_link_to_form("Stock Closing Entry", closing_entry.name)),
|
||||
title=_("Stock Closing Entry Outdated"),
|
||||
)
|
||||
|
||||
def on_submit(self):
|
||||
self.db_set("gle_processing_status", "In Progress")
|
||||
if frappe.get_single_value("Accounts Settings", "use_legacy_controller_for_pcv"):
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
import unittest
|
||||
|
||||
import frappe
|
||||
from frappe.utils import flt, today
|
||||
from frappe.utils import today
|
||||
|
||||
from erpnext.accounts.doctype.finance_book.test_finance_book import create_finance_book
|
||||
from erpnext.accounts.doctype.journal_entry.test_journal_entry import make_journal_entry
|
||||
@@ -307,218 +307,6 @@ class TestPeriodClosingVoucher(ERPNextTestSuite):
|
||||
repost_doc.posting_date = today()
|
||||
repost_doc.save()
|
||||
|
||||
def test_stock_validations_before_period_closing(self):
|
||||
from unittest.mock import patch
|
||||
|
||||
from frappe.custom.doctype.custom_field.custom_field import create_custom_fields
|
||||
|
||||
from erpnext.stock.doctype.item.test_item import make_item
|
||||
from erpnext.stock.doctype.stock_entry.stock_entry_utils import make_stock_entry
|
||||
|
||||
create_custom_fields(
|
||||
{
|
||||
"Stock Closing Entry": [
|
||||
{
|
||||
"fieldname": "warehouse",
|
||||
"label": "Warehouse",
|
||||
"fieldtype": "Link",
|
||||
"options": "Warehouse",
|
||||
}
|
||||
]
|
||||
}
|
||||
)
|
||||
|
||||
item = make_item("Test PCV Stock Item", {"is_stock_item": 1})
|
||||
se = make_stock_entry(
|
||||
item_code=item.name,
|
||||
qty=10,
|
||||
rate=100,
|
||||
to_warehouse="Stores - TPC",
|
||||
company="Test PCV Company",
|
||||
posting_date="2021-03-15",
|
||||
)
|
||||
|
||||
pcv = self.make_period_closing_voucher(posting_date="2021-03-31", submit=False)
|
||||
self.assertRaisesRegex(frappe.ValidationError, "Create a Stock Closing Entry", pcv.submit)
|
||||
|
||||
sce = frappe.get_doc(
|
||||
{
|
||||
"doctype": "Stock Closing Entry",
|
||||
"company": "Test PCV Company",
|
||||
"from_date": pcv.period_start_date,
|
||||
"to_date": pcv.period_end_date,
|
||||
"warehouse": "Stores - TPC",
|
||||
}
|
||||
).insert()
|
||||
|
||||
with patch("erpnext.stock.doctype.stock_closing_entry.stock_closing_entry.enqueue"):
|
||||
sce.submit()
|
||||
|
||||
sce.db_set("status", "Completed")
|
||||
|
||||
pcv.reload()
|
||||
self.assertRaisesRegex(frappe.ValidationError, "Create a Stock Closing Entry", pcv.submit)
|
||||
|
||||
frappe.db.set_value("Stock Closing Entry", sce.name, {"warehouse": None, "status": "In Progress"})
|
||||
|
||||
pcv.reload()
|
||||
self.assertRaisesRegex(frappe.ValidationError, "is not completed yet", pcv.submit)
|
||||
|
||||
sce.create_stock_closing_balance_entries()
|
||||
sce.db_set("status", "Completed")
|
||||
|
||||
sle = frappe.db.get_value(
|
||||
"Stock Ledger Entry",
|
||||
{"voucher_no": se.name},
|
||||
["name", "stock_value_difference"],
|
||||
as_dict=1,
|
||||
)
|
||||
frappe.db.set_value(
|
||||
"Stock Ledger Entry", sle.name, "stock_value_difference", sle.stock_value_difference + 100
|
||||
)
|
||||
|
||||
pcv.reload()
|
||||
self.assertRaisesRegex(frappe.ValidationError, "does not match", pcv.submit)
|
||||
|
||||
frappe.db.set_value(
|
||||
"Stock Ledger Entry", sle.name, "stock_value_difference", sle.stock_value_difference
|
||||
)
|
||||
|
||||
pcv.reload()
|
||||
self.assertRaisesRegex(frappe.ValidationError, "Regenerate", pcv.submit)
|
||||
|
||||
self.rebuild_stock_closing_balance(sce)
|
||||
pcv.reload()
|
||||
pcv.submit()
|
||||
self.assertEqual(pcv.docstatus, 1)
|
||||
|
||||
def test_batch_valuation_seeded_from_stock_closing_after_period_closing(self):
|
||||
from erpnext.stock.doctype.item.test_item import make_item
|
||||
from erpnext.stock.doctype.serial_and_batch_bundle.test_serial_and_batch_bundle import (
|
||||
get_batch_from_bundle,
|
||||
)
|
||||
from erpnext.stock.doctype.stock_entry.stock_entry_utils import make_stock_entry
|
||||
|
||||
item = make_item(
|
||||
"Test PCV Batch Item",
|
||||
{
|
||||
"is_stock_item": 1,
|
||||
"has_batch_no": 1,
|
||||
"create_new_batch": 1,
|
||||
"batch_number_series": "TPCVB.####",
|
||||
},
|
||||
)
|
||||
se1 = make_stock_entry(
|
||||
item_code=item.name,
|
||||
qty=10,
|
||||
rate=100,
|
||||
to_warehouse="Stores - TPC",
|
||||
company="Test PCV Company",
|
||||
posting_date="2021-03-15",
|
||||
)
|
||||
batch_no = get_batch_from_bundle(se1.items[0].serial_and_batch_bundle)
|
||||
make_stock_entry(
|
||||
item_code=item.name,
|
||||
qty=10,
|
||||
rate=200,
|
||||
to_warehouse="Stores - TPC",
|
||||
company="Test PCV Company",
|
||||
posting_date="2021-06-15",
|
||||
batch_no=batch_no,
|
||||
)
|
||||
|
||||
pcv = self.make_period_closing_voucher(posting_date="2021-03-31", submit=False)
|
||||
sce = self.make_completed_stock_closing_entry(pcv.period_start_date, pcv.period_end_date)
|
||||
pcv.reload()
|
||||
pcv.submit()
|
||||
|
||||
outward = make_stock_entry(
|
||||
item_code=item.name,
|
||||
qty=5,
|
||||
from_warehouse="Stores - TPC",
|
||||
company="Test PCV Company",
|
||||
posting_date="2022-04-01",
|
||||
batch_no=batch_no,
|
||||
)
|
||||
stock_value_difference = frappe.db.get_value(
|
||||
"Stock Ledger Entry",
|
||||
{"voucher_no": outward.name, "is_cancelled": 0},
|
||||
"stock_value_difference",
|
||||
)
|
||||
self.assertEqual(flt(stock_value_difference, 2), -750.0)
|
||||
|
||||
self.assertRaisesRegex(
|
||||
frappe.ValidationError,
|
||||
"frozen",
|
||||
make_stock_entry,
|
||||
item_code=item.name,
|
||||
qty=1,
|
||||
rate=100,
|
||||
to_warehouse="Stores - TPC",
|
||||
company="Test PCV Company",
|
||||
posting_date="2021-05-01",
|
||||
)
|
||||
self.assertRaisesRegex(frappe.ValidationError, "frozen", se1.cancel)
|
||||
self.assertRaisesRegex(frappe.ValidationError, "closed accounting period", sce.cancel)
|
||||
|
||||
def test_period_closing_blocks_stale_stock_closing_entry(self):
|
||||
from erpnext.stock.doctype.item.test_item import make_item
|
||||
from erpnext.stock.doctype.stock_entry.stock_entry_utils import make_stock_entry
|
||||
|
||||
item = make_item("Test PCV Stock Item", {"is_stock_item": 1})
|
||||
make_stock_entry(
|
||||
item_code=item.name,
|
||||
qty=10,
|
||||
rate=100,
|
||||
to_warehouse="Stores - TPC",
|
||||
company="Test PCV Company",
|
||||
posting_date="2021-03-15",
|
||||
)
|
||||
|
||||
pcv = self.make_period_closing_voucher(posting_date="2021-03-31", submit=False)
|
||||
sce = self.make_completed_stock_closing_entry(pcv.period_start_date, pcv.period_end_date)
|
||||
|
||||
make_stock_entry(
|
||||
item_code=item.name,
|
||||
qty=5,
|
||||
rate=100,
|
||||
to_warehouse="Stores - TPC",
|
||||
company="Test PCV Company",
|
||||
posting_date="2021-05-01",
|
||||
)
|
||||
|
||||
pcv.reload()
|
||||
self.assertRaisesRegex(frappe.ValidationError, "Regenerate", pcv.submit)
|
||||
|
||||
self.rebuild_stock_closing_balance(sce)
|
||||
pcv.reload()
|
||||
pcv.submit()
|
||||
self.assertEqual(pcv.docstatus, 1)
|
||||
|
||||
def make_completed_stock_closing_entry(self, from_date, to_date):
|
||||
from unittest.mock import patch
|
||||
|
||||
sce = frappe.get_doc(
|
||||
{
|
||||
"doctype": "Stock Closing Entry",
|
||||
"company": "Test PCV Company",
|
||||
"from_date": from_date,
|
||||
"to_date": to_date,
|
||||
}
|
||||
).insert()
|
||||
|
||||
with patch("erpnext.stock.doctype.stock_closing_entry.stock_closing_entry.enqueue"):
|
||||
sce.submit()
|
||||
|
||||
sce.create_stock_closing_balance_entries()
|
||||
sce.db_set("status", "Completed")
|
||||
return sce
|
||||
|
||||
def rebuild_stock_closing_balance(self, sce):
|
||||
sce.remove_stock_closing()
|
||||
sce.create_stock_closing_balance_entries()
|
||||
sce.db_set("status", "Completed")
|
||||
|
||||
def make_period_closing_voucher(self, posting_date, submit=True):
|
||||
surplus_account = create_account()
|
||||
cost_center = create_cost_center("Test Cost Center 1")
|
||||
|
||||
@@ -1180,16 +1180,7 @@ frappe.ui.form.on("Sales Invoice", {
|
||||
}
|
||||
|
||||
frm.set_df_property("update_stock", "read_only", frm.doc.has_subcontracted);
|
||||
// frm.set_df_property mutates a per-document copy, not the doctype's shared field
|
||||
// metadata, so this always reflects the original (Customize Form) hidden value.
|
||||
const hidden_by_customization = cint(
|
||||
frappe.meta.get_docfield("Sales Invoice", "update_stock")?.hidden
|
||||
);
|
||||
frm.set_df_property(
|
||||
"update_stock",
|
||||
"hidden",
|
||||
cint(frm.doc.has_subcontracted) || hidden_by_customization
|
||||
);
|
||||
frm.toggle_display("update_stock", !frm.doc.has_subcontracted);
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
@@ -254,9 +254,6 @@ class Subscription(Document):
|
||||
"""
|
||||
Sets the status of the `Subscription`
|
||||
"""
|
||||
if self.status == "Cancelled":
|
||||
return
|
||||
|
||||
if self.is_trialling():
|
||||
self.status = "Trialing"
|
||||
elif (
|
||||
@@ -608,11 +605,6 @@ class Subscription(Document):
|
||||
1. `process_for_active`
|
||||
2. `process_for_past_due`
|
||||
"""
|
||||
# Snapshot before update_subscription_period() below can roll this forward,
|
||||
# so the cancel_at_period_end check further down still targets the period
|
||||
# that just ended, not the next one.
|
||||
current_period_end = self.current_invoice_end
|
||||
|
||||
if not self.is_current_invoice_generated(
|
||||
self.current_invoice_start, self.current_invoice_end
|
||||
) and self.can_generate_new_invoice(posting_date):
|
||||
@@ -633,8 +625,8 @@ class Subscription(Document):
|
||||
self.update_subscription_period()
|
||||
|
||||
if self.cancel_at_period_end and (
|
||||
getdate(posting_date) >= getdate(current_period_end)
|
||||
or (self.end_date and getdate(posting_date) >= getdate(self.end_date))
|
||||
getdate(posting_date) >= getdate(self.current_invoice_end)
|
||||
or getdate(posting_date) >= getdate(self.end_date)
|
||||
):
|
||||
self.cancel_subscription()
|
||||
|
||||
|
||||
@@ -614,32 +614,6 @@ class TestSubscription(ERPNextTestSuite):
|
||||
|
||||
self.assertRaises(frappe.ValidationError, subscription.process, posting_date=add_days(start_date, 7))
|
||||
|
||||
def test_subscription_cancels_at_period_end_without_end_date(self):
|
||||
# https://github.com/frappe/erpnext/issues/57761 -- generate_invoice() rolls
|
||||
# current_invoice_end forward to the next period before this check runs, so
|
||||
# with no end_date to fall back on, cancel_at_period_end must compare
|
||||
# against the period that just ended, not the (already advanced) next one.
|
||||
create_plan(
|
||||
plan_name="_Test plan name 11",
|
||||
cost=80,
|
||||
currency="INR",
|
||||
billing_interval="Day",
|
||||
billing_interval_count=3,
|
||||
)
|
||||
subscription = create_subscription(
|
||||
start_date=nowdate(),
|
||||
cancel_at_period_end=1,
|
||||
generate_invoice_at="End of the current subscription period",
|
||||
plans=[{"plan": "_Test plan name 11", "qty": 1}],
|
||||
)
|
||||
self.assertEqual(len(subscription.invoices), 0)
|
||||
period_end = subscription.current_invoice_end
|
||||
|
||||
subscription.process(posting_date=period_end)
|
||||
|
||||
self.assertEqual(subscription.status, "Cancelled")
|
||||
self.assertEqual(len(subscription.invoices), 1)
|
||||
|
||||
def test_invoice_generated_when_scheduler_runs_one_day_late(self):
|
||||
# The trigger date (period end) is long past, yet catch-up still bills the period
|
||||
# on creation (Bug 1: the check is `>= trigger`, not `== trigger`).
|
||||
@@ -800,38 +774,6 @@ class TestSubscription(ERPNextTestSuite):
|
||||
subscription.reload()
|
||||
self.assertEqual(subscription.status, "Active")
|
||||
|
||||
def test_cancelled_subscription_stays_cancelled_after_payment_and_reprocess(self):
|
||||
# https://github.com/frappe/erpnext/issues/57761
|
||||
subscription = create_subscription(
|
||||
start_date=nowdate(),
|
||||
generate_invoice_at="Beginning of the current subscription period",
|
||||
submit_invoice=1,
|
||||
cancel_at_period_end=1,
|
||||
)
|
||||
subscription.process(posting_date=nowdate())
|
||||
invoice = subscription.get_current_invoice()
|
||||
self.assertGreater(invoice.outstanding_amount, 0)
|
||||
|
||||
subscription.cancel_subscription()
|
||||
self.assertEqual(subscription.status, "Cancelled")
|
||||
cancelation_date = getdate(subscription.cancelation_date)
|
||||
self.assertIsNotNone(cancelation_date)
|
||||
|
||||
payment_entry = get_payment_entry(invoice.doctype, invoice.name, bank_account="_Test Bank - _TC")
|
||||
payment_entry.reference_no = "12345"
|
||||
payment_entry.reference_date = nowdate()
|
||||
payment_entry.submit()
|
||||
|
||||
subscription.reload()
|
||||
self.assertEqual(subscription.status, "Cancelled")
|
||||
self.assertEqual(getdate(subscription.cancelation_date), cancelation_date)
|
||||
|
||||
invoice_count = len(subscription.invoices)
|
||||
subscription.process()
|
||||
subscription.reload()
|
||||
self.assertEqual(subscription.status, "Cancelled")
|
||||
self.assertEqual(len(subscription.invoices), invoice_count)
|
||||
|
||||
def test_first_invoice_generated_on_create_for_prepaid(self):
|
||||
subscription = create_subscription(
|
||||
start_date=nowdate(),
|
||||
|
||||
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-08-02 10:09+0000\n"
|
||||
"PO-Revision-Date: 2026-08-06 10:01\n"
|
||||
"PO-Revision-Date: 2026-08-03 09:00\n"
|
||||
"Last-Translator: hello@frappe.io\n"
|
||||
"Language-Team: Persian\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
@@ -6610,7 +6610,7 @@ msgstr ""
|
||||
#. DocType 'Accounts Settings'
|
||||
#: erpnext/accounts/doctype/accounts_settings/accounts_settings.json
|
||||
msgid "Auto match and set the Party in Bank Transactions"
|
||||
msgstr "مطابقت خودکار و تنظیم طرف در تراکنشهای بانکی"
|
||||
msgstr "مطابقت خودکار و تنظیم طرف در معاملات بانکی"
|
||||
|
||||
#. Label of the reorder_section (Section Break) field in DocType 'Item'
|
||||
#: erpnext/stock/doctype/item/item.json
|
||||
@@ -7781,7 +7781,7 @@ msgstr "تراکنش بانکی"
|
||||
#: erpnext/accounts/doctype/bank/bank.json
|
||||
#: erpnext/accounts/doctype/bank_transaction_mapping/bank_transaction_mapping.json
|
||||
msgid "Bank Transaction Mapping"
|
||||
msgstr "نگاشت تراکنشهای بانکی"
|
||||
msgstr "نگاشت معاملات بانکی"
|
||||
|
||||
#. Name of a DocType
|
||||
#: erpnext/accounts/doctype/bank_transaction_payments/bank_transaction_payments.json
|
||||
@@ -20481,7 +20481,7 @@ msgstr "نگاشت فیلد"
|
||||
#. Transaction Mapping'
|
||||
#: erpnext/accounts/doctype/bank_transaction_mapping/bank_transaction_mapping.json
|
||||
msgid "Field in Bank Transaction"
|
||||
msgstr "فیلد در تراکنشهای بانکی"
|
||||
msgstr "فیلد در معاملات بانکی"
|
||||
|
||||
#: erpnext/accounts/doctype/accounting_dimension/accounting_dimension.py:95
|
||||
msgid "Fieldname Conflict"
|
||||
@@ -23790,7 +23790,7 @@ msgstr "اگر آیتمها موجود هستند، مراحل انتقال
|
||||
#. (Link) field in DocType 'Stock Settings'
|
||||
#: erpnext/stock/doctype/stock_settings/stock_settings.json
|
||||
msgid "If mentioned, the system will allow only the users with this Role to create or modify any stock transaction earlier than the latest stock transaction for a specific item and warehouse. If set as blank, it allows all users to create/edit back-dated transactions."
|
||||
msgstr "در صورت ذکر، سیستم فقط به کاربرانی که این نقش را دارند اجازه میدهد هرگونه تراکنش موجودی را قبل از آخرین تراکنش موجودی برای یک کالا و انبار خاص ایجاد یا اصلاح کنند. اگر خالی تنظیم شود، به همه کاربران اجازه میدهد تراکنشهای تاریخ گذشته را ایجاد/ویرایش کنند."
|
||||
msgstr "در صورت ذکر شده، این سیستم فقط به کاربران دارای این نقش اجازه میدهد تا هر تراکنش موجودی را زودتر از آخرین تراکنش موجودی برای یک کالا و انبار خاص ایجاد یا اصلاح کنند. اگر به صورت خالی تنظیم شود، به همه کاربران اجازه میدهد تا تراکنشهای قدیمی را ایجاد/ویرایش کنند."
|
||||
|
||||
#. Description of the 'To Package No.' (Int) field in DocType 'Packing Slip'
|
||||
#: erpnext/stock/doctype/packing_slip/packing_slip.json
|
||||
@@ -24575,7 +24575,7 @@ msgstr "شامل آیتمهای غیر موجودی"
|
||||
#: erpnext/accounts/doctype/bank_clearance/bank_clearance.json
|
||||
#: erpnext/accounts/report/bank_reconciliation_statement/bank_reconciliation_statement.js:45
|
||||
msgid "Include POS Transactions"
|
||||
msgstr "شامل تراکنشهای POS"
|
||||
msgstr "شامل معاملات POS"
|
||||
|
||||
#: erpnext/accounts/doctype/pos_invoice/pos_invoice.py:205
|
||||
msgid "Include Payment"
|
||||
@@ -33211,7 +33211,7 @@ msgstr "از طریق ایمیل اطلاع دهید"
|
||||
#. Label of the reorder_email_notify (Check) field in DocType 'Stock Settings'
|
||||
#: erpnext/stock/doctype/stock_settings/stock_settings.json
|
||||
msgid "Notify by email on creation of automatic Material Request"
|
||||
msgstr "اطلاع رسانی از طریق ایمیل در مورد ایجاد درخواست خودکار مواد"
|
||||
msgstr ""
|
||||
|
||||
#. Description of the 'Notify Via Email' (Check) field in DocType 'Appointment
|
||||
#. Booking Settings'
|
||||
@@ -35187,7 +35187,7 @@ msgstr "تنظیمات POS"
|
||||
#. Label of the pos_invoices (Table) field in DocType 'POS Closing Entry'
|
||||
#: erpnext/accounts/doctype/pos_closing_entry/pos_closing_entry.json
|
||||
msgid "POS Transactions"
|
||||
msgstr "تراکنشهای POS"
|
||||
msgstr "معاملات POS"
|
||||
|
||||
#: erpnext/selling/page/point_of_sale/pos_controller.js:178
|
||||
msgid "POS has been closed at {0}. Please refresh the page."
|
||||
@@ -38419,7 +38419,7 @@ msgstr "لطفاً یک یادداشت تحویل را انتخاب کنید"
|
||||
|
||||
#: erpnext/crm/doctype/appointment_booking_settings/appointment_booking_settings.py:81
|
||||
msgid "Please select a Holiday List to enable Appointment Scheduling."
|
||||
msgstr "لطفا برای فعال کردن زمانبندی قرار ملاقات، یک لیست تعطیلات انتخاب کنید."
|
||||
msgstr ""
|
||||
|
||||
#: erpnext/subcontracting/doctype/subcontracting_order/subcontracting_order.py:153
|
||||
msgid "Please select a Subcontracting Purchase Order."
|
||||
@@ -38500,7 +38500,7 @@ msgstr "لطفاً یک سفارش خرید معتبر که برای پیمان
|
||||
|
||||
#: erpnext/accounts/report/accounts_receivable/accounts_receivable.py:1355
|
||||
msgid "Please select a valid {0}"
|
||||
msgstr "لطفا یک {0} معتبر انتخاب کنید"
|
||||
msgstr ""
|
||||
|
||||
#: erpnext/selling/doctype/quotation/quotation.js:245
|
||||
msgid "Please select a value for {0} quotation_to {1}"
|
||||
@@ -42679,7 +42679,7 @@ msgstr "RFQ برای {0} مجاز نیست به دلیل رتبه کارت ام
|
||||
#. Label of the auto_indent (Check) field in DocType 'Stock Settings'
|
||||
#: erpnext/stock/doctype/stock_settings/stock_settings.json
|
||||
msgid "Raise Material Request when stock reaches re-order level"
|
||||
msgstr "ثبت درخواست مواد زمانی که موجودی به سطح سفارش مجدد رسید"
|
||||
msgstr ""
|
||||
|
||||
#. Label of the complaint_raised_by (Data) field in DocType 'Warranty Claim'
|
||||
#: erpnext/support/doctype/warranty_claim/warranty_claim.json
|
||||
@@ -43312,7 +43312,7 @@ msgstr ""
|
||||
|
||||
#: erpnext/stock/doctype/bin/bin.js:10
|
||||
msgid "Recalculate Values"
|
||||
msgstr "محاسبه مجدد مقادیر"
|
||||
msgstr ""
|
||||
|
||||
#. Option for the 'Status' (Select) field in DocType 'Asset'
|
||||
#. Option for the 'Purpose' (Select) field in DocType 'Asset Movement'
|
||||
@@ -45060,7 +45060,7 @@ msgstr "انبار رزرو شده برای آیتم {item_code} در مواد
|
||||
|
||||
#: erpnext/stock/report/stock_projected_qty/stock_projected_qty.py:198
|
||||
msgid "Reserved for POS Transactions"
|
||||
msgstr "برای تراکنشهای POS رزرو شده است"
|
||||
msgstr "برای معاملات POS رزرو شده است"
|
||||
|
||||
#: erpnext/stock/report/stock_projected_qty/stock_projected_qty.py:177
|
||||
msgid "Reserved for Production"
|
||||
@@ -48420,7 +48420,7 @@ msgstr "زمانبند غیرفعال است. نمیتوان حسابها
|
||||
|
||||
#: erpnext/accounts/doctype/repost_accounting_ledger/repost_accounting_ledger.py:232
|
||||
msgid "Scheduler is inactive. Reposting will only run once background jobs are processed."
|
||||
msgstr "زمانبند غیرفعال است. ارسال مجدد فقط زمانی اجرا میشود که کارهای پسزمینه پردازش شوند."
|
||||
msgstr ""
|
||||
|
||||
#. Label of the schedules (Table) field in DocType 'Maintenance Schedule'
|
||||
#: erpnext/maintenance/doctype/maintenance_schedule/maintenance_schedule.json
|
||||
@@ -48851,7 +48851,7 @@ msgstr "انتخاب آدرس تامین کننده"
|
||||
|
||||
#: erpnext/stock/doctype/material_request/material_request.js:448
|
||||
msgid "Select Supplier for Items"
|
||||
msgstr "انتخاب تامین کننده برای آیتمها"
|
||||
msgstr ""
|
||||
|
||||
#: erpnext/stock/doctype/batch/batch.js:150
|
||||
msgid "Select Target Warehouse"
|
||||
@@ -48905,7 +48905,7 @@ msgstr "یک تامین کننده انتخاب کنید"
|
||||
#: erpnext/stock/doctype/material_request/material_request.js:552
|
||||
#: erpnext/stock/doctype/material_request/material_request.py:699
|
||||
msgid "Select a Supplier for Item {0}"
|
||||
msgstr "انتخاب یک تأمینکننده برای آیتم {0}"
|
||||
msgstr ""
|
||||
|
||||
#: banking/src/components/features/BankReconciliation/MatchAndReconcile.tsx:49
|
||||
msgid "Select a bank account to reconcile"
|
||||
@@ -48946,7 +48946,7 @@ msgstr "از هر مجموعه یک آیتم را برای استفاده در
|
||||
#: erpnext/stock/doctype/material_request/material_request.js:539
|
||||
#: erpnext/stock/doctype/material_request/material_request.py:680
|
||||
msgid "Select at least one Item"
|
||||
msgstr "حداقل یک آیتم را انتخاب کنید"
|
||||
msgstr ""
|
||||
|
||||
#: erpnext/stock/doctype/item/item.js:944
|
||||
msgid "Select at least one attribute value."
|
||||
@@ -49265,7 +49265,7 @@ msgstr "ارسال با پیوست"
|
||||
#: erpnext/accounts/doctype/payment_request/payment_request.js:51
|
||||
#: erpnext/accounts/doctype/payment_request/payment_request.js:55
|
||||
msgid "Sending Email"
|
||||
msgstr "ارسال ایمیل"
|
||||
msgstr ""
|
||||
|
||||
#. Option for the 'Detected Amount Format' (Select) field in DocType 'Bank
|
||||
#. Statement Import Log'
|
||||
@@ -50094,7 +50094,7 @@ msgstr "تنظیم تامین کننده"
|
||||
|
||||
#: erpnext/stock/doctype/material_request/material_request.js:455
|
||||
msgid "Set Supplier for All Items"
|
||||
msgstr "تنظیم تأمینکننده برای همه آیتمها"
|
||||
msgstr ""
|
||||
|
||||
#. Label of the set_target_warehouse (Link) field in DocType 'Sales Invoice'
|
||||
#. Label of the set_warehouse (Link) field in DocType 'Purchase Order'
|
||||
@@ -53005,7 +53005,7 @@ msgstr "پیشفاکتور خود را ارسال کنید"
|
||||
|
||||
#: erpnext/manufacturing/doctype/job_card/job_card.py:1524
|
||||
msgid "Submitted Job Card cannot be processed."
|
||||
msgstr "کارت کار ارسالشده قابل پردازش نیست."
|
||||
msgstr "کارت شغلی ارسالشده قابل پردازش نیست."
|
||||
|
||||
#. Label of the subscription_section (Section Break) field in DocType 'Payment
|
||||
#. Request'
|
||||
@@ -56021,7 +56021,7 @@ msgstr "این گزینه برای ویرایش فیلدهای «تاریخ ار
|
||||
#. level' (Check) field in DocType 'Stock Settings'
|
||||
#: erpnext/stock/doctype/stock_settings/stock_settings.json
|
||||
msgid "This option is useful if you want to ensure a constant supply of raw materials/products and avoid shortage. A Material Request will be raised automatically when stock reached the re-order level defined in the Item form."
|
||||
msgstr "این گزینه در صورتی مفید است که بخواهید از تأمین مداوم مواد اولیه/محصولات اطمینان حاصل کنید و از کمبود جلوگیری کنید. درخواست مواد به طور خودکار زمانی که موجودی به سطح سفارش مجدد تعریف شده در فرم کالا برسد، ایجاد میشود."
|
||||
msgstr ""
|
||||
|
||||
#: banking/src/components/features/BankReconciliation/IncorrectlyClearedEntries.tsx:180
|
||||
msgid "This report shows all entries in the system where the <strong>clearance date is before the posting date</strong> which is incorrect."
|
||||
@@ -60041,7 +60041,7 @@ msgstr ""
|
||||
#. Label of the verification_token (Data) field in DocType 'Appointment'
|
||||
#: erpnext/crm/doctype/appointment/appointment.json
|
||||
msgid "Verification Token"
|
||||
msgstr "توکن تأیید"
|
||||
msgstr ""
|
||||
|
||||
#: erpnext/www/book_appointment/verify/index.html:15
|
||||
msgid "Verification failed please check the link"
|
||||
@@ -60907,7 +60907,7 @@ msgstr ""
|
||||
|
||||
#: erpnext/templates/emails/appointment_confirmed.html:3
|
||||
msgid "We look forward to meeting you"
|
||||
msgstr "مشتاق دیدار شما هستیم"
|
||||
msgstr ""
|
||||
|
||||
#: banking/src/pages/BankStatementImporter.tsx:169
|
||||
msgid "We support uploading CSV, XLSX, XLS and PDF files. Please make sure the file contains the correct columns."
|
||||
|
||||
@@ -3,7 +3,7 @@ msgstr ""
|
||||
"Project-Id-Version: frappe\n"
|
||||
"Report-Msgid-Bugs-To: hello@frappe.io\n"
|
||||
"POT-Creation-Date: 2026-08-02 10:09+0000\n"
|
||||
"PO-Revision-Date: 2026-08-06 10:01\n"
|
||||
"PO-Revision-Date: 2026-08-03 09:00\n"
|
||||
"Last-Translator: hello@frappe.io\n"
|
||||
"Language-Team: Croatian\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
@@ -152,7 +152,7 @@ msgstr "% Završeno Metoda"
|
||||
|
||||
#: erpnext/projects/doctype/project/project.py:226
|
||||
msgid "% Complete must be between 0 and 100"
|
||||
msgstr "% dovršenosti mora biti između 0 i 100"
|
||||
msgstr ""
|
||||
|
||||
#. Label of the percent_complete (Percent) field in DocType 'Project'
|
||||
#: erpnext/projects/doctype/project/project.json
|
||||
@@ -349,7 +349,7 @@ msgstr "'Ažuriraj Zalihe' ne može se provjeriti za prodaju osnovne Imovine"
|
||||
|
||||
#: erpnext/crm/doctype/appointment_booking_settings/appointment_booking_settings.py:112
|
||||
msgid "'Verification Link Expiry Duration' must be between 15 to 60 minutes."
|
||||
msgstr "'Trajanje Važenja Verifikacijske Poveznice' mora biti između 15 i 60 minuta."
|
||||
msgstr ""
|
||||
|
||||
#: erpnext/accounts/doctype/bank_account/bank_account.py:79
|
||||
msgid "'{0}' account is already used by {1}. Use another account."
|
||||
@@ -1118,7 +1118,7 @@ msgstr "Onemogućeni Paket Artikal ne može se odabrati u transakcijama."
|
||||
|
||||
#: erpnext/accounts/doctype/exchange_rate_revaluation/exchange_rate_revaluation.py:636
|
||||
msgid "A draft reverse journal for {0} has been created: {1}"
|
||||
msgstr "Nacrt obrnutog naloga knjiženja za {0} je izrađen: {1}"
|
||||
msgstr ""
|
||||
|
||||
#: erpnext/stock/doctype/delivery_trip/delivery_trip.py:59
|
||||
msgid "A driver must be set to submit."
|
||||
@@ -1163,7 +1163,7 @@ msgstr "Kontrola Kvaliteta mora biti izvršena prije izdavanja Nabavnog Računa
|
||||
|
||||
#: erpnext/stock/doctype/material_request/material_request.js:476
|
||||
msgid "A separate Purchase Order is created for each Supplier."
|
||||
msgstr "Za svakog Dobavljača izrađuje se zasebni Nalog Nabave."
|
||||
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"
|
||||
@@ -1176,7 +1176,7 @@ msgstr "Distributer / trgovac / komisionar / podružnica / preprodavač treće s
|
||||
|
||||
#: erpnext/crm/doctype/appointment/appointment.py:70
|
||||
msgid "A verified appointment cannot be moved back to 'Unverified' status."
|
||||
msgstr "Potvrđeni termin se ne može vratiti u status 'Neverificirano'."
|
||||
msgstr ""
|
||||
|
||||
#. Option for the 'Blood Group' (Select) field in DocType 'Employee'
|
||||
#: erpnext/setup/doctype/employee/employee.json
|
||||
@@ -2367,7 +2367,7 @@ msgstr "Radnja je Pokrenuta"
|
||||
#. DocType 'Appointment Booking Settings'
|
||||
#: erpnext/crm/doctype/appointment_booking_settings/appointment_booking_settings.json
|
||||
msgid "Action for Expired Unverified Appointments"
|
||||
msgstr "Radnja za Istekle Nepotvrđene Termine"
|
||||
msgstr ""
|
||||
|
||||
#. Label of the action_if_accumulated_monthly_budget_exceeded (Select) field in
|
||||
#. DocType 'Budget'
|
||||
@@ -2913,7 +2913,7 @@ msgstr "Dodaj sve račune na koje želite podijeliti transakciju."
|
||||
|
||||
#: erpnext/accounts/doctype/repost_accounting_ledger/repost_accounting_ledger.py:92
|
||||
msgid "Add atleast one voucher to repost."
|
||||
msgstr "Dodaj barem jedan verifikat za ponovno knjiženje."
|
||||
msgstr ""
|
||||
|
||||
#: erpnext/www/book_appointment/index.html:42
|
||||
msgid "Add details"
|
||||
@@ -3430,7 +3430,7 @@ msgstr "Iznos Predujma"
|
||||
|
||||
#: erpnext/crm/doctype/appointment_booking_settings/appointment_booking_settings.py:93
|
||||
msgid "Advance Booking Days is mandatory for Appointment Scheduling."
|
||||
msgstr "Prethodna Rezervacija Dana je obavezna za Zakazivanje Termina."
|
||||
msgstr ""
|
||||
|
||||
#. Label of the advance_paid (Currency) field in DocType 'Sales Order'
|
||||
#: erpnext/selling/doctype/sales_order/sales_order.json
|
||||
@@ -3753,7 +3753,7 @@ msgstr "Dob ({0})"
|
||||
#: erpnext/accounts/report/accounts_receivable/accounts_receivable.js:102
|
||||
#: erpnext/accounts/report/accounts_receivable_summary/accounts_receivable_summary.js:28
|
||||
msgid "Age as on"
|
||||
msgstr "Dob na"
|
||||
msgstr ""
|
||||
|
||||
#. Label of the ageing_based_on (Select) field in DocType 'Process Statement Of
|
||||
#. Accounts'
|
||||
@@ -5107,7 +5107,7 @@ msgstr "Grupa Artikla je način za klasifikaciju Artikala na temelju tipa."
|
||||
|
||||
#: erpnext/crm/doctype/appointment/appointment.py:74
|
||||
msgid "An appointment booked through the portal can only be opened via email verification."
|
||||
msgstr "Termin rezerviran putem portala može se otvoriti samo putem potvrde e-poštom."
|
||||
msgstr ""
|
||||
|
||||
#. Description of the 'Notify by email on creation of automatic Material
|
||||
#. Request' (Check) field in DocType 'Stock Settings'
|
||||
@@ -5505,7 +5505,7 @@ msgstr "Imenovanje"
|
||||
#. Booking Settings'
|
||||
#: erpnext/crm/doctype/appointment_booking_settings/appointment_booking_settings.json
|
||||
msgid "Appointment Booking Portal Settings"
|
||||
msgstr "Postavke Portala za Zakazivanje Termina"
|
||||
msgstr ""
|
||||
|
||||
#. Name of a DocType
|
||||
#. Label of a Workspace Sidebar Item
|
||||
@@ -5525,7 +5525,7 @@ msgstr "Potvrda Termina"
|
||||
|
||||
#: erpnext/crm/doctype/appointment/appointment.py:189
|
||||
msgid "Appointment Confirmed"
|
||||
msgstr "Termin Potvrđen"
|
||||
msgstr ""
|
||||
|
||||
#: erpnext/www/book_appointment/index.js:237
|
||||
msgid "Appointment Created Successfully"
|
||||
@@ -5547,7 +5547,7 @@ msgstr "Trajanje Termina (u minutama)"
|
||||
#. 'Appointment Booking Settings'
|
||||
#: erpnext/crm/doctype/appointment_booking_settings/appointment_booking_settings.json
|
||||
msgid "Appointment Scheduling"
|
||||
msgstr "Zakazivanje Termina"
|
||||
msgstr ""
|
||||
|
||||
#: erpnext/www/book_appointment/index.py:24
|
||||
msgid "Appointment Scheduling Disabled"
|
||||
@@ -5559,7 +5559,7 @@ msgstr "Zakazivanje termina je onemogućeno za ovu stranicu"
|
||||
|
||||
#: erpnext/crm/doctype/appointment_booking_settings/appointment_booking_settings.py:101
|
||||
msgid "Appointment Scheduling needs to be enabled for Appointment Booking through portal."
|
||||
msgstr "Zakazivanje Termina mora biti omogućeno za Rezervaciju Termina putem portala."
|
||||
msgstr ""
|
||||
|
||||
#. Label of the appointment_with (Link) field in DocType 'Appointment'
|
||||
#: erpnext/crm/doctype/appointment/appointment.json
|
||||
@@ -5568,31 +5568,31 @@ msgstr "Termin s"
|
||||
|
||||
#: erpnext/crm/doctype/appointment/appointment.py:86
|
||||
msgid "Appointment can only be scheduled up to {0} day(s) in advance."
|
||||
msgstr "Termin se može zakazati samo do {0} dana unaprijed."
|
||||
msgstr ""
|
||||
|
||||
#: erpnext/crm/doctype/appointment/appointment.py:79
|
||||
msgid "Appointment cannot be scheduled for a past time."
|
||||
msgstr "Termin se ne može zakazati za prošlo vrijeme."
|
||||
msgstr ""
|
||||
|
||||
#: erpnext/crm/doctype/appointment/appointment.py:98
|
||||
msgid "Appointment cannot be scheduled on a holiday."
|
||||
msgstr "Termin se ne može zakazati na praznik."
|
||||
msgstr ""
|
||||
|
||||
#: erpnext/www/book_appointment/verify/index.py:28
|
||||
msgid "Appointment has been closed. Please book the appointment again."
|
||||
msgstr "Termin je zatvoren. Ponovo zakažete novi termin."
|
||||
msgstr ""
|
||||
|
||||
#: erpnext/www/book_appointment/verify/index.py:33
|
||||
msgid "Appointment is already verified."
|
||||
msgstr "Termin je već potvrđen."
|
||||
msgstr ""
|
||||
|
||||
#: erpnext/crm/doctype/appointment/appointment.py:116
|
||||
msgid "Appointment must be scheduled within the available slot timings."
|
||||
msgstr "Termin se mora zakazati unutar raspoloživih vremenskih utora."
|
||||
msgstr ""
|
||||
|
||||
#: erpnext/crm/doctype/appointment/appointment.py:66
|
||||
msgid "Appointments created manually cannot have 'Unverified' status."
|
||||
msgstr "Ručno rezervirani termini ne mogu imati status 'Nepotvrđeno'."
|
||||
msgstr ""
|
||||
|
||||
#. Label of the approving_role (Link) field in DocType 'Authorization Rule'
|
||||
#: erpnext/setup/doctype/authorization_rule/authorization_rule.json
|
||||
@@ -8649,7 +8649,7 @@ msgstr "Spremnik"
|
||||
|
||||
#: erpnext/stock/doctype/bin/bin.js:16
|
||||
msgid "Bin Values Recalculated"
|
||||
msgstr "Vrijednosti Spremnika Ponovo Izračunate"
|
||||
msgstr ""
|
||||
|
||||
#. Label of the bio (Text Editor) field in DocType 'Employee'
|
||||
#: erpnext/setup/doctype/employee/employee.json
|
||||
@@ -8784,7 +8784,7 @@ msgstr "Blokiraj Dostavljača"
|
||||
#. 'Accounts Settings'
|
||||
#: erpnext/accounts/doctype/accounts_settings/accounts_settings.json
|
||||
msgid "Block a new Sales Invoice when the customer's overdue amount exceeds the Overdue Limit set on the customer."
|
||||
msgstr "Blokiraj novu Prodajnu Fakturu kada iznos dospjelog plaćanja klijenta premaši ograničenje dospjelog plaćanja postavljeno za klijenta."
|
||||
msgstr ""
|
||||
|
||||
#. Description of the 'Is Frozen' (Check) field in DocType 'Customer'
|
||||
#: erpnext/selling/doctype/customer/customer.json
|
||||
@@ -9868,7 +9868,7 @@ msgstr "Sastavnica se nemože deaktivirati ili otkazati jer je povezana sa drugi
|
||||
|
||||
#: erpnext/crm/doctype/opportunity/opportunity.py:282
|
||||
msgid "Cannot declare as Lost because an active Quotation exists."
|
||||
msgstr "Ne može se proglasiti izgubljeno jer postoji aktivna Ponuda."
|
||||
msgstr ""
|
||||
|
||||
#: erpnext/accounts/doctype/purchase_taxes_and_charges_template/purchase_taxes_and_charges_template.js:16
|
||||
#: erpnext/accounts/doctype/purchase_taxes_and_charges_template/purchase_taxes_and_charges_template.js:26
|
||||
@@ -9977,7 +9977,7 @@ msgstr "Ne može se upućivati na broj reda veći ili jednak trenutnom broju red
|
||||
|
||||
#: erpnext/accounts/doctype/repost_accounting_ledger/repost_accounting_ledger.py:96
|
||||
msgid "Cannot repost more than {0} vouchers at once. Split them into multiple documents."
|
||||
msgstr "Nije moguće ponovo knjižiti više od {0} verifikata odjednom. Podijeli ih u više dokumenata."
|
||||
msgstr ""
|
||||
|
||||
#: erpnext/accounts/doctype/bank/bank.js:63
|
||||
msgid "Cannot retrieve link token for update. Check Error Log for more information"
|
||||
@@ -13863,7 +13863,7 @@ msgstr "Izrađeno Migracijom"
|
||||
#. Label of the created_through_portal (Check) field in DocType 'Appointment'
|
||||
#: erpnext/crm/doctype/appointment/appointment.json
|
||||
msgid "Created through Portal"
|
||||
msgstr "Izrađeno putem Portala"
|
||||
msgstr ""
|
||||
|
||||
#: erpnext/buying/doctype/supplier_scorecard/supplier_scorecard.py:251
|
||||
msgid "Created {0} scorecards for {1} between:"
|
||||
@@ -16439,7 +16439,7 @@ msgstr "Obriši Potencijalne Klijente i Adrese"
|
||||
#. in DocType 'Appointment Booking Settings'
|
||||
#: erpnext/crm/doctype/appointment_booking_settings/appointment_booking_settings.json
|
||||
msgid "Delete Permanently"
|
||||
msgstr "Trajno Izbriši"
|
||||
msgstr ""
|
||||
|
||||
#. Label of the delete_transactions_status (Select) field in DocType
|
||||
#. 'Transaction Deletion Record'
|
||||
@@ -18421,7 +18421,7 @@ msgstr "Kopiraj red {0} sa istim {1}"
|
||||
|
||||
#: erpnext/accounts/doctype/repost_accounting_ledger/repost_accounting_ledger.py:110
|
||||
msgid "Duplicate vouchers found. Remove the duplicate vouchers to continue to repost."
|
||||
msgstr "Pronađeni su duplikati verifikata. Ukloni duplikate verifikata da biste nastavili s ponovnim knjiženjem."
|
||||
msgstr ""
|
||||
|
||||
#: erpnext/accounts/doctype/pricing_rule/pricing_rule.py:157
|
||||
msgid "Duplicate {0} found in the table"
|
||||
@@ -18742,11 +18742,11 @@ msgstr "E-pošta poslana Dobavljaču {0}"
|
||||
#. Label of the email_verified (Check) field in DocType 'Appointment'
|
||||
#: erpnext/crm/doctype/appointment/appointment.json
|
||||
msgid "Email Verified"
|
||||
msgstr "E-pošta Potvrđena"
|
||||
msgstr ""
|
||||
|
||||
#: erpnext/accounts/doctype/payment_request/payment_request.js:57
|
||||
msgid "Email couldn't be sent."
|
||||
msgstr "E-pošta nije mogla biti poslana."
|
||||
msgstr ""
|
||||
|
||||
#: erpnext/setup/doctype/employee/employee.py:440
|
||||
msgid "Email is required to create a user"
|
||||
@@ -18994,7 +18994,7 @@ msgstr "Omogući Dozvoli Djelomičnu Rezervaciju u Postavkama Zaliha da rezervi
|
||||
#. Booking Settings'
|
||||
#: erpnext/crm/doctype/appointment_booking_settings/appointment_booking_settings.json
|
||||
msgid "Enable Appointment Booking Through Portal"
|
||||
msgstr "Omogući Zakazivanje Termina Putem Portala"
|
||||
msgstr ""
|
||||
|
||||
#. Label of the enable_scheduling (Check) field in DocType 'Appointment Booking
|
||||
#. Settings'
|
||||
@@ -23386,7 +23386,7 @@ msgstr "Lista Praznika"
|
||||
|
||||
#: erpnext/crm/doctype/appointment_booking_settings/appointment_booking_settings.py:89
|
||||
msgid "Holiday List - {0} is not valid for current date."
|
||||
msgstr "Popis Praznika - {0} nije valjan za trenutni datum."
|
||||
msgstr ""
|
||||
|
||||
#. Label of the holiday_list_name (Data) field in DocType 'Holiday List'
|
||||
#: erpnext/setup/doctype/holiday_list/holiday_list.json
|
||||
@@ -24361,7 +24361,7 @@ msgstr "U Minutama"
|
||||
#. DocType 'Appointment Booking Settings'
|
||||
#: erpnext/crm/doctype/appointment_booking_settings/appointment_booking_settings.json
|
||||
msgid "In Minutes (min: 15 mins, max: 60 mins)"
|
||||
msgstr "U minutama (min: 15 min, maks: 60 min)"
|
||||
msgstr ""
|
||||
|
||||
#: erpnext/accounts/report/accounts_payable/accounts_payable.js:149
|
||||
#: erpnext/accounts/report/accounts_receivable/accounts_receivable.js:181
|
||||
@@ -28024,7 +28024,7 @@ msgstr "Artikal {0} nemože se dodati kao sam podsklop"
|
||||
|
||||
#: erpnext/stock/doctype/material_request/material_request.py:694
|
||||
msgid "Item {0} cannot be ordered more than once"
|
||||
msgstr "Artikal {0} se ne može naručiti više od jednom"
|
||||
msgstr ""
|
||||
|
||||
#: erpnext/manufacturing/doctype/blanket_order/blanket_order.py:197
|
||||
msgid "Item {0} cannot be ordered more than {1} against Blanket Order {2}."
|
||||
@@ -30466,7 +30466,7 @@ msgstr "Označi kao Zatvoreno"
|
||||
#. in DocType 'Appointment Booking Settings'
|
||||
#: erpnext/crm/doctype/appointment_booking_settings/appointment_booking_settings.json
|
||||
msgid "Mark as Closed"
|
||||
msgstr "Odaberi kao Zatvoreno"
|
||||
msgstr ""
|
||||
|
||||
#. Description of the 'Is Internal Customer' (Check) field in DocType
|
||||
#. 'Customer'
|
||||
@@ -32423,7 +32423,7 @@ msgstr "Nova Prodajna Faktura"
|
||||
#. Credit Limit'
|
||||
#: erpnext/selling/doctype/customer_credit_limit/customer_credit_limit.json
|
||||
msgid "New Sales Invoices are blocked when the customer's overdue amount exceeds this. Requires 'Restrict Customer Over Billing' in Accounts Settings."
|
||||
msgstr "Nove prodajne fakture se blokiraju kada iznos dospjelog duga klijenta premaši ovaj iznos. Zahtijeva opciju 'Ograniči Prekomjerno Fakturisanje Klijenta' u Postavkama Knjiženja."
|
||||
msgstr ""
|
||||
|
||||
#. Label of the sales_order (Check) field in DocType 'Email Digest'
|
||||
#: erpnext/setup/doctype/email_digest/email_digest.json
|
||||
@@ -32680,7 +32680,7 @@ msgstr "Nema dostupnih dodatnih polja"
|
||||
|
||||
#: erpnext/crm/doctype/appointment/appointment.py:103
|
||||
msgid "No availability of slots are found. Please add on Appointment Booking Settings."
|
||||
msgstr "Nije pronađeno nikakvo slobodno vrijeme termina. Dodaj ih u Postavkama Zakazivanja Termina."
|
||||
msgstr ""
|
||||
|
||||
#: erpnext/stock/doctype/stock_reservation_entry/stock_reservation_entry.py:1367
|
||||
msgid "No available quantity to reserve for item {0} in warehouse {1}"
|
||||
@@ -34859,15 +34859,15 @@ msgstr "Dana Zakašnjenja"
|
||||
#. Credit Limit'
|
||||
#: erpnext/selling/doctype/customer_credit_limit/customer_credit_limit.json
|
||||
msgid "Overdue Limit"
|
||||
msgstr "Granica Dospijeća"
|
||||
msgstr ""
|
||||
|
||||
#: erpnext/selling/doctype/customer/customer.py:707
|
||||
msgid "Overdue Limit Crossed"
|
||||
msgstr "Granica Dospijeća Prekoračena"
|
||||
msgstr ""
|
||||
|
||||
#: erpnext/selling/doctype/customer/customer.py:702
|
||||
msgid "Overdue Limit crossed for customer {0}. Overdue amount {1} exceeds the allowed limit {2}."
|
||||
msgstr "Granica Dospijeća prekoračena je za {0}. Iznos dospijeća {1} prelazi dozvoljenu granicu {2}."
|
||||
msgstr ""
|
||||
|
||||
#. Name of a DocType
|
||||
#: erpnext/accounts/doctype/overdue_payment/overdue_payment.json
|
||||
@@ -35798,7 +35798,7 @@ msgstr "Djelimično Usaglašeno"
|
||||
#. Option for the 'Status' (Select) field in DocType 'Repost Accounting Ledger'
|
||||
#: erpnext/accounts/doctype/repost_accounting_ledger/repost_accounting_ledger.json
|
||||
msgid "Partially Reposted"
|
||||
msgstr "Djelomično Ponovo Knjiženo"
|
||||
msgstr ""
|
||||
|
||||
#. Option for the 'Status' (Select) field in DocType 'Stock Reservation Entry'
|
||||
#: erpnext/stock/doctype/stock_reservation_entry/stock_reservation_entry.json
|
||||
@@ -36562,7 +36562,7 @@ msgstr "Ograničenje Plaćanja"
|
||||
|
||||
#: erpnext/accounts/doctype/payment_request/payment_request.py:434
|
||||
msgid "Payment Link couldn't be sent."
|
||||
msgstr "Poveznica za plaćanje nije mogla biti poslana."
|
||||
msgstr ""
|
||||
|
||||
#: erpnext/accounts/report/pos_register/pos_register.js:50
|
||||
#: erpnext/accounts/report/pos_register/pos_register.py:126
|
||||
@@ -37884,7 +37884,7 @@ msgstr "Dodaj Račun za Privremeno Otvaranje u Kontni Plan"
|
||||
|
||||
#: erpnext/crm/doctype/appointment/appointment.py:95
|
||||
msgid "Please add a valid Holiday List on Appointment Booking Settings."
|
||||
msgstr "Dodaj valjani Popis Praznika u Postavke Zakazivanja Termina."
|
||||
msgstr ""
|
||||
|
||||
#: erpnext/accounts/doctype/bank_transaction_rule/bank_transaction_rule.py:119
|
||||
msgid "Please add an account for the Bank Entry rule."
|
||||
@@ -38269,7 +38269,7 @@ msgstr "Popuni Tabelu Prodajnih Naloga"
|
||||
|
||||
#: erpnext/crm/doctype/appointment_booking_settings/appointment_booking_settings.py:57
|
||||
msgid "Please fill up the Availability of Slots table to enable Appointment Scheduling."
|
||||
msgstr "Popuni tablicu Dostupnosti Termina kako biste omogućili Zakazivanje Termina."
|
||||
msgstr ""
|
||||
|
||||
#: erpnext/stock/doctype/shipment/shipment.js:277
|
||||
msgid "Please first set Full Name, Email and Phone for the user"
|
||||
@@ -38513,7 +38513,7 @@ msgstr "Odaberi Dostavnicu"
|
||||
|
||||
#: erpnext/crm/doctype/appointment_booking_settings/appointment_booking_settings.py:81
|
||||
msgid "Please select a Holiday List to enable Appointment Scheduling."
|
||||
msgstr "Odaberi Popis Praznika kako biste omogućili Zakazivanje Termina."
|
||||
msgstr ""
|
||||
|
||||
#: erpnext/subcontracting/doctype/subcontracting_order/subcontracting_order.py:153
|
||||
msgid "Please select a Subcontracting Purchase Order."
|
||||
@@ -38594,7 +38594,7 @@ msgstr "Odaberi važeći Nalog Nabave koji je konfigurisan za Podugovor."
|
||||
|
||||
#: erpnext/accounts/report/accounts_receivable/accounts_receivable.py:1355
|
||||
msgid "Please select a valid {0}"
|
||||
msgstr "Odaberi valjani {0}"
|
||||
msgstr ""
|
||||
|
||||
#: erpnext/selling/doctype/quotation/quotation.js:245
|
||||
msgid "Please select a value for {0} quotation_to {1}"
|
||||
@@ -42540,12 +42540,12 @@ msgstr "Količina ne može biti veća od {0} za artikal {1}"
|
||||
|
||||
#: erpnext/stock/doctype/material_request/material_request.py:704
|
||||
msgid "Quantity for Item {0} must be greater than zero and cannot exceed {1}"
|
||||
msgstr "Količina za Artikal {0} mora biti veća od nule i ne može biti veća od {1}"
|
||||
msgstr ""
|
||||
|
||||
#: erpnext/stock/doctype/material_request/material_request.js:564
|
||||
msgctxt "<b>${pending_qty}</b>"
|
||||
msgid "Quantity for Item {0} must be greater than zero and cannot exceed {1}"
|
||||
msgstr "Količina za Artikal {0} mora biti veća od nule i ne može biti veća od {1}"
|
||||
msgstr ""
|
||||
|
||||
#: erpnext/subcontracting/doctype/subcontracting_order/subcontracting_order.js:564
|
||||
msgid "Quantity is mandatory for the selected items."
|
||||
@@ -43406,7 +43406,7 @@ msgstr "Ponovo izračunaj Stopu Vrednovanja"
|
||||
|
||||
#: erpnext/stock/doctype/bin/bin.js:10
|
||||
msgid "Recalculate Values"
|
||||
msgstr "Preračunaj Vrijednosti"
|
||||
msgstr ""
|
||||
|
||||
#. Option for the 'Status' (Select) field in DocType 'Asset'
|
||||
#. Option for the 'Purpose' (Select) field in DocType 'Asset Movement'
|
||||
@@ -44608,7 +44608,7 @@ msgstr "Ponovno Knjiženje je započeto u pozadini"
|
||||
#. Items'
|
||||
#: erpnext/accounts/doctype/repost_accounting_ledger_items/repost_accounting_ledger_items.json
|
||||
msgid "Reposted"
|
||||
msgstr "Ponovno Knjiženo"
|
||||
msgstr ""
|
||||
|
||||
#. Label of the reposting_data_file (Attach) field in DocType 'Repost Item
|
||||
#. Valuation'
|
||||
@@ -44636,7 +44636,7 @@ msgstr "Referansa Ponovnog knjiženja"
|
||||
#. 'Repost Accounting Ledger Items'
|
||||
#: erpnext/accounts/doctype/repost_accounting_ledger_items/repost_accounting_ledger_items.json
|
||||
msgid "Reposting Status"
|
||||
msgstr "Status Ponovnog Knjiženja"
|
||||
msgstr ""
|
||||
|
||||
#. Label of the vouchers_based_on_item_and_warehouse_section (Section Break)
|
||||
#. field in DocType 'Repost Item Valuation'
|
||||
@@ -44650,11 +44650,11 @@ msgstr "Napred Ponovnog Knjiženja Kaučera"
|
||||
|
||||
#: erpnext/accounts/doctype/repost_accounting_ledger/repost_accounting_ledger.py:216
|
||||
msgid "Reposting can be started only for submitted document."
|
||||
msgstr "Ponovno Knjiženje se može pokrenuti samo za podnešeni dokument."
|
||||
msgstr ""
|
||||
|
||||
#: erpnext/accounts/doctype/repost_accounting_ledger/repost_accounting_ledger.py:221
|
||||
msgid "Reposting cannot be started when status is {0}."
|
||||
msgstr "Ponovno Knjiženje se ne može pokrenuti kada je status {0}."
|
||||
msgstr ""
|
||||
|
||||
#: erpnext/stock/report/stock_and_account_value_comparison/stock_and_account_value_comparison.py:227
|
||||
#: erpnext/stock/report/stock_ledger_invariant_check/stock_ledger_invariant_check.py:338
|
||||
@@ -44679,11 +44679,11 @@ msgstr "Ponovno Knjiženje u pozadini."
|
||||
|
||||
#: erpnext/accounts/doctype/repost_accounting_ledger/repost_accounting_ledger.py:211
|
||||
msgid "Reposting is still in progress in background."
|
||||
msgstr "Ponovno knjiženje je još uvijek u tijeku u pozadini."
|
||||
msgstr ""
|
||||
|
||||
#: erpnext/accounts/doctype/repost_accounting_ledger/repost_accounting_ledger.py:315
|
||||
msgid "Reposting {0} {1}"
|
||||
msgstr "Ponovno knjiženje {0} {1}"
|
||||
msgstr ""
|
||||
|
||||
#. Label of the represents_company (Link) field in DocType 'Purchase Invoice'
|
||||
#. Label of the represents_company (Link) field in DocType 'Sales Invoice'
|
||||
@@ -45356,7 +45356,7 @@ msgstr "Ograniči"
|
||||
#. 'Accounts Settings'
|
||||
#: erpnext/accounts/doctype/accounts_settings/accounts_settings.json
|
||||
msgid "Restrict Customer Over Billing"
|
||||
msgstr "Ograničiti Prekomjerno Fakturisanje Klijenta"
|
||||
msgstr ""
|
||||
|
||||
#. Label of the restrict_based_on (Select) field in DocType 'Party Specific
|
||||
#. Item'
|
||||
@@ -45678,7 +45678,7 @@ msgstr "Obrnuta Signatura"
|
||||
|
||||
#: erpnext/accounts/doctype/exchange_rate_revaluation/exchange_rate_revaluation.py:628
|
||||
msgid "Reverse {0} already available in draft status: {1}"
|
||||
msgstr "Obrnuto {0} već je dostupno u statusu nacrta: {1}"
|
||||
msgstr ""
|
||||
|
||||
#: erpnext/accounts/doctype/exchange_rate_revaluation/exchange_rate_revaluation.js:118
|
||||
msgid "Reversing Journals..."
|
||||
@@ -45807,7 +45807,7 @@ msgstr "Štap"
|
||||
#. 'Accounts Settings'
|
||||
#: erpnext/accounts/doctype/accounts_settings/accounts_settings.json
|
||||
msgid "Role Allowed to Bypass Over Billing Restriction"
|
||||
msgstr "Uloga kojoj je dopušteno zaobilaženje Ograničenja Prekomjernog Fakturisanja"
|
||||
msgstr ""
|
||||
|
||||
#. Label of the role_allowed_to_over_deliver_receive (Link) field in DocType
|
||||
#. 'Stock Settings'
|
||||
@@ -48518,7 +48518,7 @@ msgstr "Raspoređivač je neaktivan. Nije moguće spojiti račune."
|
||||
|
||||
#: erpnext/accounts/doctype/repost_accounting_ledger/repost_accounting_ledger.py:232
|
||||
msgid "Scheduler is inactive. Reposting will only run once background jobs are processed."
|
||||
msgstr "Zakazivač je neaktivan. Ponovno Knjiženje će se pokrenuti tek nakon što se obrade pozadinski zadaci."
|
||||
msgstr ""
|
||||
|
||||
#. Label of the schedules (Table) field in DocType 'Maintenance Schedule'
|
||||
#: erpnext/maintenance/doctype/maintenance_schedule/maintenance_schedule.json
|
||||
@@ -48951,7 +48951,7 @@ msgstr "Odaberi Adresu Dobavljača"
|
||||
|
||||
#: erpnext/stock/doctype/material_request/material_request.js:448
|
||||
msgid "Select Supplier for Items"
|
||||
msgstr "Odaberi Dobavljača za Artikle"
|
||||
msgstr ""
|
||||
|
||||
#: erpnext/stock/doctype/batch/batch.js:150
|
||||
msgid "Select Target Warehouse"
|
||||
@@ -49005,7 +49005,7 @@ msgstr "Odaberi Dobavljača"
|
||||
#: erpnext/stock/doctype/material_request/material_request.js:552
|
||||
#: erpnext/stock/doctype/material_request/material_request.py:699
|
||||
msgid "Select a Supplier for Item {0}"
|
||||
msgstr "Odaberi Dobavljača za Artikal {0}"
|
||||
msgstr ""
|
||||
|
||||
#: banking/src/components/features/BankReconciliation/MatchAndReconcile.tsx:49
|
||||
msgid "Select a bank account to reconcile"
|
||||
@@ -49046,7 +49046,7 @@ msgstr "Odaber artikal iz svakog skupa koja će se koristiti u Prodajnom Nalogu.
|
||||
#: erpnext/stock/doctype/material_request/material_request.js:539
|
||||
#: erpnext/stock/doctype/material_request/material_request.py:680
|
||||
msgid "Select at least one Item"
|
||||
msgstr "Odaberi barem jedan Artikal"
|
||||
msgstr ""
|
||||
|
||||
#: erpnext/stock/doctype/item/item.js:944
|
||||
msgid "Select at least one attribute value."
|
||||
@@ -49365,7 +49365,7 @@ msgstr "Pošalji sa Prilogom"
|
||||
#: erpnext/accounts/doctype/payment_request/payment_request.js:51
|
||||
#: erpnext/accounts/doctype/payment_request/payment_request.js:55
|
||||
msgid "Sending Email"
|
||||
msgstr "Slanje e-pošte u tijeku"
|
||||
msgstr ""
|
||||
|
||||
#. Option for the 'Detected Amount Format' (Select) field in DocType 'Bank
|
||||
#. Statement Import Log'
|
||||
@@ -50194,7 +50194,7 @@ msgstr "Postavi Dobavljača"
|
||||
|
||||
#: erpnext/stock/doctype/material_request/material_request.js:455
|
||||
msgid "Set Supplier for All Items"
|
||||
msgstr "Postavi Dobavljača za Sve Artikle"
|
||||
msgstr ""
|
||||
|
||||
#. Label of the set_target_warehouse (Link) field in DocType 'Sales Invoice'
|
||||
#. Label of the set_warehouse (Link) field in DocType 'Purchase Order'
|
||||
@@ -52609,7 +52609,7 @@ msgstr "Zaliha nije dostupna za Artikal {0} u Skladištu {1}."
|
||||
|
||||
#: erpnext/stock/doctype/stock_reservation_entry/stock_reservation_entry.py:1240
|
||||
msgid "Stock not available to reserve for the Item {0} in Warehouse {1}."
|
||||
msgstr "Zaliha nije dostupna za rezervaciju za Artikal {0} u Skladištu {1}."
|
||||
msgstr ""
|
||||
|
||||
#: erpnext/selling/page/point_of_sale/pos_controller.js:826
|
||||
msgid "Stock quantity not enough for Item Code: {0} under warehouse {1}. Available quantity {2} {3}."
|
||||
@@ -55286,7 +55286,7 @@ msgstr "Računa pod Obavezama ili Kapitalom, u kojoj će se knjižiti Rezultat"
|
||||
|
||||
#: erpnext/accounts/doctype/account/account.py:222
|
||||
msgid "The account type of {0} cannot be changed from {1} because stock ledger entries exist against it."
|
||||
msgstr "Tip računa {0} ne može se promijeniti iz {1} jer postoje unosi u Registru Zaliha."
|
||||
msgstr ""
|
||||
|
||||
#: erpnext/accounts/doctype/payment_request/payment_request.py:1016
|
||||
msgid "The allocated amount is greater than the outstanding amount of Payment Request {0}"
|
||||
@@ -55444,7 +55444,7 @@ msgstr "Sljedeći redovi su duplikati:"
|
||||
|
||||
#: erpnext/accounts/doctype/repost_accounting_ledger/repost_accounting_ledger.py:130
|
||||
msgid "The following vouchers are not submitted: {0}"
|
||||
msgstr "Sljedeći verifikati nisu podnešeni: {0}"
|
||||
msgstr ""
|
||||
|
||||
#: erpnext/stock/doctype/material_request/material_request.py:1062
|
||||
msgid "The following {0} were created: {1}"
|
||||
@@ -55956,7 +55956,7 @@ msgstr "Ovaj dokument je preko ograničenja za {0} {1} za artikal {4}. Da li pra
|
||||
|
||||
#: erpnext/templates/emails/appointment_confirmed.html:6
|
||||
msgid "This email was sent from {0}"
|
||||
msgstr "Ova e-pošta je poslana od {0}"
|
||||
msgstr ""
|
||||
|
||||
#: erpnext/stock/doctype/delivery_note/delivery_note.js:496
|
||||
msgid "This field is used to set the 'Customer'."
|
||||
@@ -56102,7 +56102,7 @@ msgstr "Ovaj filter artikala je već primijenjen za {0}"
|
||||
|
||||
#: erpnext/templates/emails/confirm_appointment.html:4
|
||||
msgid "This link is valid for {0} minutes"
|
||||
msgstr "Ova poveznica vrijedi {0} minuta"
|
||||
msgstr ""
|
||||
|
||||
#: erpnext/www/banking.py:35
|
||||
msgid "This method is only meant for developer mode"
|
||||
@@ -56223,7 +56223,7 @@ msgstr "Ova vrijednost će se koristiti kada se ne pronađe odgovarajući Zajedn
|
||||
|
||||
#: erpnext/www/book_appointment/verify/index.py:18
|
||||
msgid "This verification link is invalid. Please book the appointment again."
|
||||
msgstr "Ova poveznica za verifikaciju je nevažeća. Ponovo zakaži termin."
|
||||
msgstr ""
|
||||
|
||||
#: banking/src/components/features/Settings/Preferences.tsx:86
|
||||
msgid "This will automatically run transaction matching rules on unreconciled transactions every hour."
|
||||
@@ -58030,7 +58030,7 @@ msgstr "Transakcije naspram Tvrtke već postoje! Kontni Plan se može uvesti sam
|
||||
#. 'Customer'
|
||||
#: erpnext/selling/doctype/customer/customer.json
|
||||
msgid "Transactions are blocked when the outstanding balance exceeds the credit limit. When Restrict Customer Over Billing is enabled, new invoices are also blocked when the customer's overdue amount exceeds the Overdue Limit."
|
||||
msgstr "Transakcije se blokiraju kada preostali dug premaši kreditnu granicu. Kada je omogućena opcija Ograniči Prekomjerno Fakturisanja Klijenta, nove fakture se također blokiraju kada iznos dospjelih obaveza klijenta premaši granicu za dospjele obaveze."
|
||||
msgstr ""
|
||||
|
||||
#: banking/src/components/features/BankStatementImporter/CSV/StatementDetails.tsx:239
|
||||
msgid "Transactions to be imported into the system"
|
||||
@@ -58651,7 +58651,7 @@ msgstr "Poništi Dodjele"
|
||||
|
||||
#: erpnext/accounts/doctype/repost_accounting_ledger/repost_accounting_ledger.py:375
|
||||
msgid "Unable to Repost Accounting Ledger"
|
||||
msgstr "Ponovo knjiži Knjigovodstveni Registar"
|
||||
msgstr ""
|
||||
|
||||
#: erpnext/setup/doctype/transaction_deletion_record/transaction_deletion_record.py:477
|
||||
msgid "Unable to fetch DocType details. Please contact system administrator."
|
||||
@@ -59594,7 +59594,7 @@ msgstr "Korisnicima sa ovom ulogom je dozvoljena prekomjerna Dostava/Primanje na
|
||||
#. field in DocType 'Accounts Settings'
|
||||
#: erpnext/accounts/doctype/accounts_settings/accounts_settings.json
|
||||
msgid "Users with this role can still submit invoices for customers who have crossed their Overdue Limit."
|
||||
msgstr "Korisnici s ovom ulogom i dalje mogu podnositi fakture za klijente koji su prekoračili granicu dospjelosti."
|
||||
msgstr ""
|
||||
|
||||
#. Description of the 'Role to Notify on Depreciation Failure' (Link) field in
|
||||
#. DocType 'Accounts Settings'
|
||||
@@ -60141,12 +60141,12 @@ msgstr "Rizični Kapital"
|
||||
#. 'Appointment Booking Settings'
|
||||
#: erpnext/crm/doctype/appointment_booking_settings/appointment_booking_settings.json
|
||||
msgid "Verification Link Expiry Duration"
|
||||
msgstr "Trajanje Vađenaj Verifikacijske Poveznice"
|
||||
msgstr ""
|
||||
|
||||
#. Label of the verification_token (Data) field in DocType 'Appointment'
|
||||
#: erpnext/crm/doctype/appointment/appointment.json
|
||||
msgid "Verification Token"
|
||||
msgstr "Verifikacijski Kod"
|
||||
msgstr ""
|
||||
|
||||
#: erpnext/www/book_appointment/verify/index.html:15
|
||||
msgid "Verification failed please check the link"
|
||||
@@ -60154,7 +60154,7 @@ msgstr "Verifikacija nije uspjela, provjeri vezu"
|
||||
|
||||
#: erpnext/www/book_appointment/verify/index.py:38
|
||||
msgid "Verification link has expired."
|
||||
msgstr "Veza za provjeru je istekla."
|
||||
msgstr ""
|
||||
|
||||
#. Label of the verified_by (Data) field in DocType 'Quality Inspection'
|
||||
#: erpnext/stock/doctype/quality_inspection/quality_inspection.json
|
||||
@@ -61012,7 +61012,7 @@ msgstr "Vidimo da je {0} napravljen protiv {1}. Ako želite da se ažuriraju pre
|
||||
|
||||
#: erpnext/templates/emails/appointment_confirmed.html:3
|
||||
msgid "We look forward to meeting you"
|
||||
msgstr "Radujemo se susretu s vama"
|
||||
msgstr ""
|
||||
|
||||
#: banking/src/pages/BankStatementImporter.tsx:169
|
||||
msgid "We support uploading CSV, XLSX, XLS and PDF files. Please make sure the file contains the correct columns."
|
||||
@@ -62123,7 +62123,7 @@ msgstr "Vaše Ime (obavezno)"
|
||||
|
||||
#: erpnext/templates/emails/appointment_confirmed.html:2
|
||||
msgid "Your email has been verified and your appointment has been confirmed for {0}"
|
||||
msgstr "Vaša e-pošta je potvrđena i vaš termin je potvrđen za {0}"
|
||||
msgstr ""
|
||||
|
||||
#: erpnext/www/book_appointment/verify/index.html:11
|
||||
msgid "Your email has been verified and your appointment has been scheduled"
|
||||
@@ -62948,7 +62948,7 @@ msgstr "Prikaz {0} trenutno nije podržan u Prilagođenom Financijskom Izvješć
|
||||
|
||||
#: erpnext/stock/doctype/material_request/material_request.py:732
|
||||
msgid "{0} was set to today for items whose requested date has passed"
|
||||
msgstr "{0} je postavljen na danas za artikle čiji je traženi datum prošao"
|
||||
msgstr ""
|
||||
|
||||
#: erpnext/accounts/doctype/payment_term/payment_term.js:19
|
||||
msgid "{0} will be given as discount."
|
||||
|
||||
@@ -3,7 +3,7 @@ msgstr ""
|
||||
"Project-Id-Version: frappe\n"
|
||||
"Report-Msgid-Bugs-To: hello@frappe.io\n"
|
||||
"POT-Creation-Date: 2026-08-02 10:09+0000\n"
|
||||
"PO-Revision-Date: 2026-08-06 10:01\n"
|
||||
"PO-Revision-Date: 2026-08-04 09:43\n"
|
||||
"Last-Translator: hello@frappe.io\n"
|
||||
"Language-Team: Swedish\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
@@ -152,7 +152,7 @@ msgstr "% Klart Sätt"
|
||||
|
||||
#: erpnext/projects/doctype/project/project.py:226
|
||||
msgid "% Complete must be between 0 and 100"
|
||||
msgstr "% Färdig måste vara mellan 0 och 100"
|
||||
msgstr ""
|
||||
|
||||
#. Label of the percent_complete (Percent) field in DocType 'Project'
|
||||
#: erpnext/projects/doctype/project/project.json
|
||||
@@ -349,7 +349,7 @@ msgstr "\"Uppdatera Lager\" kan inte väljas för Fast Tillgång Försäljning"
|
||||
|
||||
#: erpnext/crm/doctype/appointment_booking_settings/appointment_booking_settings.py:112
|
||||
msgid "'Verification Link Expiry Duration' must be between 15 to 60 minutes."
|
||||
msgstr "'Verifiering Länk Utgång Tid' måste vara mellan 15 och 60 minuter."
|
||||
msgstr ""
|
||||
|
||||
#: erpnext/accounts/doctype/bank_account/bank_account.py:79
|
||||
msgid "'{0}' account is already used by {1}. Use another account."
|
||||
@@ -1125,7 +1125,7 @@ msgstr "Inaktiverad Artikel Paket kan inte väljas i transaktioner."
|
||||
|
||||
#: erpnext/accounts/doctype/exchange_rate_revaluation/exchange_rate_revaluation.py:636
|
||||
msgid "A draft reverse journal for {0} has been created: {1}"
|
||||
msgstr "Utkast till omvänd journal för {0} har skapats: {1}"
|
||||
msgstr ""
|
||||
|
||||
#: erpnext/stock/doctype/delivery_trip/delivery_trip.py:59
|
||||
msgid "A driver must be set to submit."
|
||||
@@ -1170,7 +1170,7 @@ msgstr "Kvalitet kontroll måste genomföras innan Inköp Följesedel skapas fö
|
||||
|
||||
#: erpnext/stock/doctype/material_request/material_request.js:476
|
||||
msgid "A separate Purchase Order is created for each Supplier."
|
||||
msgstr "Separat Inköp Order skapas för varje Leverantör."
|
||||
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"
|
||||
@@ -1183,7 +1183,7 @@ msgstr "Tredje parts distributör / handlare / kommissionär / återförsäljare
|
||||
|
||||
#: erpnext/crm/doctype/appointment/appointment.py:70
|
||||
msgid "A verified appointment cannot be moved back to 'Unverified' status."
|
||||
msgstr "Verifierad bokning kan inte flyttas tillbaka till \"Overifierad\" status."
|
||||
msgstr ""
|
||||
|
||||
#. Option for the 'Blood Group' (Select) field in DocType 'Employee'
|
||||
#: erpnext/setup/doctype/employee/employee.json
|
||||
@@ -2374,7 +2374,7 @@ msgstr "Åtgärd Initierad"
|
||||
#. DocType 'Appointment Booking Settings'
|
||||
#: erpnext/crm/doctype/appointment_booking_settings/appointment_booking_settings.json
|
||||
msgid "Action for Expired Unverified Appointments"
|
||||
msgstr "Åtgärd för Utgångna, Overifierade Bokningar"
|
||||
msgstr ""
|
||||
|
||||
#. Label of the action_if_accumulated_monthly_budget_exceeded (Select) field in
|
||||
#. DocType 'Budget'
|
||||
@@ -2920,7 +2920,7 @@ msgstr "Lägg till alla konton som du vill dela upp transaktion i."
|
||||
|
||||
#: erpnext/accounts/doctype/repost_accounting_ledger/repost_accounting_ledger.py:92
|
||||
msgid "Add atleast one voucher to repost."
|
||||
msgstr "Lägg till minst ett verifikat för att bokföra om."
|
||||
msgstr ""
|
||||
|
||||
#: erpnext/www/book_appointment/index.html:42
|
||||
msgid "Add details"
|
||||
@@ -3437,7 +3437,7 @@ msgstr "Förskott Belopp"
|
||||
|
||||
#: erpnext/crm/doctype/appointment_booking_settings/appointment_booking_settings.py:93
|
||||
msgid "Advance Booking Days is mandatory for Appointment Scheduling."
|
||||
msgstr "Förhandsbokning erfordras för Tdsbokning Schemaläggning."
|
||||
msgstr ""
|
||||
|
||||
#. Label of the advance_paid (Currency) field in DocType 'Sales Order'
|
||||
#: erpnext/selling/doctype/sales_order/sales_order.json
|
||||
@@ -3760,7 +3760,7 @@ msgstr "Ålder ({0})"
|
||||
#: erpnext/accounts/report/accounts_receivable/accounts_receivable.js:102
|
||||
#: erpnext/accounts/report/accounts_receivable_summary/accounts_receivable_summary.js:28
|
||||
msgid "Age as on"
|
||||
msgstr "Ålder per"
|
||||
msgstr ""
|
||||
|
||||
#. Label of the ageing_based_on (Select) field in DocType 'Process Statement Of
|
||||
#. Accounts'
|
||||
@@ -5114,7 +5114,7 @@ msgstr "Artikel grupp är ett sätt att klassificera artiklar baserat på typer.
|
||||
|
||||
#: erpnext/crm/doctype/appointment/appointment.py:74
|
||||
msgid "An appointment booked through the portal can only be opened via email verification."
|
||||
msgstr "Bokad tid via portal kan endast öppnas via e-post verifiering."
|
||||
msgstr ""
|
||||
|
||||
#. Description of the 'Notify by email on creation of automatic Material
|
||||
#. Request' (Check) field in DocType 'Stock Settings'
|
||||
@@ -5512,7 +5512,7 @@ msgstr "Möte"
|
||||
#. Booking Settings'
|
||||
#: erpnext/crm/doctype/appointment_booking_settings/appointment_booking_settings.json
|
||||
msgid "Appointment Booking Portal Settings"
|
||||
msgstr "Tid Bokning Portal Inställningar"
|
||||
msgstr ""
|
||||
|
||||
#. Name of a DocType
|
||||
#. Label of a Workspace Sidebar Item
|
||||
@@ -5532,7 +5532,7 @@ msgstr "Tid Bokning Bekräftelse"
|
||||
|
||||
#: erpnext/crm/doctype/appointment/appointment.py:189
|
||||
msgid "Appointment Confirmed"
|
||||
msgstr "Tidsbokning Bekräftad"
|
||||
msgstr ""
|
||||
|
||||
#: erpnext/www/book_appointment/index.js:237
|
||||
msgid "Appointment Created Successfully"
|
||||
@@ -5554,7 +5554,7 @@ msgstr "Tid Bokning Varar (Minuter)"
|
||||
#. 'Appointment Booking Settings'
|
||||
#: erpnext/crm/doctype/appointment_booking_settings/appointment_booking_settings.json
|
||||
msgid "Appointment Scheduling"
|
||||
msgstr "Tidsbokning Schemaläggning"
|
||||
msgstr ""
|
||||
|
||||
#: erpnext/www/book_appointment/index.py:24
|
||||
msgid "Appointment Scheduling Disabled"
|
||||
@@ -5566,7 +5566,7 @@ msgstr "Tid Bokning är Inaktiverad för denna Webbplats"
|
||||
|
||||
#: erpnext/crm/doctype/appointment_booking_settings/appointment_booking_settings.py:101
|
||||
msgid "Appointment Scheduling needs to be enabled for Appointment Booking through portal."
|
||||
msgstr "Tidsbokning Schemaläggning måste vara aktiverad för Tidsbokning via portal."
|
||||
msgstr ""
|
||||
|
||||
#. Label of the appointment_with (Link) field in DocType 'Appointment'
|
||||
#: erpnext/crm/doctype/appointment/appointment.json
|
||||
@@ -5575,31 +5575,31 @@ msgstr "Tid Bokning med"
|
||||
|
||||
#: erpnext/crm/doctype/appointment/appointment.py:86
|
||||
msgid "Appointment can only be scheduled up to {0} day(s) in advance."
|
||||
msgstr "Tidsbokning kan endast schemaläggas upp till {0} dag(ar) i förväg."
|
||||
msgstr ""
|
||||
|
||||
#: erpnext/crm/doctype/appointment/appointment.py:79
|
||||
msgid "Appointment cannot be scheduled for a past time."
|
||||
msgstr "Tidsbokning kan inte schemaläggas för förfluten tid."
|
||||
msgstr ""
|
||||
|
||||
#: erpnext/crm/doctype/appointment/appointment.py:98
|
||||
msgid "Appointment cannot be scheduled on a holiday."
|
||||
msgstr "Tidsbokning kan inte schemaläggas på helgdag."
|
||||
msgstr ""
|
||||
|
||||
#: erpnext/www/book_appointment/verify/index.py:28
|
||||
msgid "Appointment has been closed. Please book the appointment again."
|
||||
msgstr "Tidsbokning har stängts. Boka igen."
|
||||
msgstr ""
|
||||
|
||||
#: erpnext/www/book_appointment/verify/index.py:33
|
||||
msgid "Appointment is already verified."
|
||||
msgstr "Tidsbokning är redan bekräftad."
|
||||
msgstr ""
|
||||
|
||||
#: erpnext/crm/doctype/appointment/appointment.py:116
|
||||
msgid "Appointment must be scheduled within the available slot timings."
|
||||
msgstr "Tidsbokning måste schemaläggas inom tillgänglig tidsintervall."
|
||||
msgstr ""
|
||||
|
||||
#: erpnext/crm/doctype/appointment/appointment.py:66
|
||||
msgid "Appointments created manually cannot have 'Unverified' status."
|
||||
msgstr "Tidsbokningar som skapas manuellt kan inte ha ”Overifierad” status."
|
||||
msgstr ""
|
||||
|
||||
#. Label of the approving_role (Link) field in DocType 'Authorization Rule'
|
||||
#: erpnext/setup/doctype/authorization_rule/authorization_rule.json
|
||||
@@ -8791,7 +8791,7 @@ msgstr "Spärra Leverantör"
|
||||
#. 'Accounts Settings'
|
||||
#: erpnext/accounts/doctype/accounts_settings/accounts_settings.json
|
||||
msgid "Block a new Sales Invoice when the customer's overdue amount exceeds the Overdue Limit set on the customer."
|
||||
msgstr "Spärra ny Försäljning Faktura när kundens förfallna belopp överstiger förfallen gräns angiven för kund."
|
||||
msgstr ""
|
||||
|
||||
#. Description of the 'Is Frozen' (Check) field in DocType 'Customer'
|
||||
#: erpnext/selling/doctype/customer/customer.json
|
||||
@@ -9875,7 +9875,7 @@ msgstr "Kan inte inaktivera eller annullera Stycklista eftersom den är kopplat
|
||||
|
||||
#: erpnext/crm/doctype/opportunity/opportunity.py:282
|
||||
msgid "Cannot declare as Lost because an active Quotation exists."
|
||||
msgstr "Kan inte ange som förlorad eftersom det finns aktiv Offert."
|
||||
msgstr ""
|
||||
|
||||
#: erpnext/accounts/doctype/purchase_taxes_and_charges_template/purchase_taxes_and_charges_template.js:16
|
||||
#: erpnext/accounts/doctype/purchase_taxes_and_charges_template/purchase_taxes_and_charges_template.js:26
|
||||
@@ -9984,7 +9984,7 @@ msgstr "Kan inte hänvisa till rad nummer högre än eller lika med aktuell rad
|
||||
|
||||
#: erpnext/accounts/doctype/repost_accounting_ledger/repost_accounting_ledger.py:96
|
||||
msgid "Cannot repost more than {0} vouchers at once. Split them into multiple documents."
|
||||
msgstr "Kunde inte återbokföra fler än {0} verifikationer samtidigt. Dela upp dem i flera dokument."
|
||||
msgstr ""
|
||||
|
||||
#: erpnext/accounts/doctype/bank/bank.js:63
|
||||
msgid "Cannot retrieve link token for update. Check Error Log for more information"
|
||||
@@ -13870,7 +13870,7 @@ msgstr "Skapad av Migrering"
|
||||
#. Label of the created_through_portal (Check) field in DocType 'Appointment'
|
||||
#: erpnext/crm/doctype/appointment/appointment.json
|
||||
msgid "Created through Portal"
|
||||
msgstr "Skapad via Portal"
|
||||
msgstr ""
|
||||
|
||||
#: erpnext/buying/doctype/supplier_scorecard/supplier_scorecard.py:251
|
||||
msgid "Created {0} scorecards for {1} between:"
|
||||
@@ -16446,7 +16446,7 @@ msgstr "Ta bort Prospekt och Adresser"
|
||||
#. in DocType 'Appointment Booking Settings'
|
||||
#: erpnext/crm/doctype/appointment_booking_settings/appointment_booking_settings.json
|
||||
msgid "Delete Permanently"
|
||||
msgstr "Ta bort Permanent"
|
||||
msgstr ""
|
||||
|
||||
#. Label of the delete_transactions_status (Select) field in DocType
|
||||
#. 'Transaction Deletion Record'
|
||||
@@ -18342,7 +18342,7 @@ msgstr "Påminnelse Typ"
|
||||
|
||||
#: erpnext/accounts/doctype/pos_profile/pos_profile.py:170
|
||||
msgid "Duplicate Customer Group"
|
||||
msgstr "Duplicera Kund Grupp"
|
||||
msgstr "Kopiera Kund Grupp"
|
||||
|
||||
#: erpnext/setup/doctype/transaction_deletion_record/transaction_deletion_record.py:190
|
||||
msgid "Duplicate DocType"
|
||||
@@ -18354,11 +18354,11 @@ msgstr "Dubblett Post. Kontrollera Auktorisering Regel {0}"
|
||||
|
||||
#: erpnext/assets/doctype/asset/asset.py:418
|
||||
msgid "Duplicate Finance Book"
|
||||
msgstr "Duplicera Bokslut Register"
|
||||
msgstr "Kopiera Bokslut Register"
|
||||
|
||||
#: erpnext/accounts/doctype/pos_profile/pos_profile.py:164
|
||||
msgid "Duplicate Item Group"
|
||||
msgstr "Duplicera Artikel Grupp"
|
||||
msgstr "Kopiera Artikel Grupp"
|
||||
|
||||
#: erpnext/manufacturing/doctype/bom_creator/bom_creator.py:102
|
||||
msgid "Duplicate Item Under Same Parent"
|
||||
@@ -18376,7 +18376,7 @@ msgstr "Duplicera Kassa Fällt"
|
||||
#: erpnext/accounts/doctype/pos_closing_entry/pos_closing_entry.py:104
|
||||
#: erpnext/accounts/doctype/pos_invoice_merge_log/pos_invoice_merge_log.py:64
|
||||
msgid "Duplicate POS Invoices found"
|
||||
msgstr "Dubblett av Kassa Fakturor hittad"
|
||||
msgstr "Kopia av Kassa Fakturor hittad"
|
||||
|
||||
#: erpnext/accounts/doctype/payment_request/payment_request.py:134
|
||||
msgid "Duplicate Payment Schedule selected"
|
||||
@@ -18384,7 +18384,7 @@ msgstr "Duplicerad Betalning Schema vald"
|
||||
|
||||
#: erpnext/projects/doctype/project/project.js:83
|
||||
msgid "Duplicate Project with Tasks"
|
||||
msgstr "Duplicera Projekt med Uppgifter"
|
||||
msgstr "Kopiera Projekt med Uppgifter"
|
||||
|
||||
#: erpnext/accounts/doctype/pos_closing_entry/pos_closing_entry.py:157
|
||||
msgid "Duplicate Sales Invoices found"
|
||||
@@ -18404,7 +18404,7 @@ msgstr "Kopia av Kund Grupp finns i Kund Grupp Tabell"
|
||||
|
||||
#: erpnext/stock/doctype/item_manufacturer/item_manufacturer.py:44
|
||||
msgid "Duplicate entry against the item code {0} and manufacturer {1}"
|
||||
msgstr "Duplicera post mot artikel kod {0} och producent {1}"
|
||||
msgstr "Kopiera post mot Artikel Kod {0} och Producent {1}"
|
||||
|
||||
#: erpnext/setup/doctype/transaction_deletion_record/transaction_deletion_record.py:189
|
||||
msgid "Duplicate entry: {0}{1}"
|
||||
@@ -18412,27 +18412,27 @@ msgstr "Duplicerad post: {0}{1}"
|
||||
|
||||
#: erpnext/accounts/doctype/pos_profile/pos_profile.py:164
|
||||
msgid "Duplicate item group found in the item group table"
|
||||
msgstr "Dubblett av Artikel Grupp hittad i Artikel Grupp Tabell"
|
||||
msgstr "Kopiera Artikel Grupp hittad i Artikel Grupp Tabell"
|
||||
|
||||
#: erpnext/accounts/doctype/dunning_type/dunning_type.py:133
|
||||
msgid "Duplicate languages found on Dunning Letter Text. Keep only one of them."
|
||||
msgstr "Det finns flera språk i Påminnelse Brev. Behåll endast ett språk."
|
||||
msgstr "Det finns flera språk i påminnelse brev. Behåll endast ett språk."
|
||||
|
||||
#: erpnext/projects/doctype/project/project.js:186
|
||||
msgid "Duplicate project has been created"
|
||||
msgstr "Dubblett av Projekt är skapad"
|
||||
msgstr "Kopia av Projekt är skapad"
|
||||
|
||||
#: erpnext/utilities/transaction_base.py:112
|
||||
msgid "Duplicate row {0} with same {1}"
|
||||
msgstr "Duplicera Rad {0} med samma {1}"
|
||||
msgstr "Kopiera Rad {0} med samma {1}"
|
||||
|
||||
#: erpnext/accounts/doctype/repost_accounting_ledger/repost_accounting_ledger.py:110
|
||||
msgid "Duplicate vouchers found. Remove the duplicate vouchers to continue to repost."
|
||||
msgstr "Dubbletter av verifikat hittades. Ta bort dubbletter för att fortsätta återbokföring."
|
||||
msgstr ""
|
||||
|
||||
#: erpnext/accounts/doctype/pricing_rule/pricing_rule.py:157
|
||||
msgid "Duplicate {0} found in the table"
|
||||
msgstr "Dubblett {0} hittades i Tabell"
|
||||
msgstr "Kopia {0} hittades i Tabell"
|
||||
|
||||
#. Label of the duration (Int) field in DocType 'Task'
|
||||
#: erpnext/projects/doctype/task/task.json
|
||||
@@ -18749,11 +18749,11 @@ msgstr "E-post Skickad till Leverantör {0}"
|
||||
#. Label of the email_verified (Check) field in DocType 'Appointment'
|
||||
#: erpnext/crm/doctype/appointment/appointment.json
|
||||
msgid "Email Verified"
|
||||
msgstr "E-post Verifierad"
|
||||
msgstr ""
|
||||
|
||||
#: erpnext/accounts/doctype/payment_request/payment_request.js:57
|
||||
msgid "Email couldn't be sent."
|
||||
msgstr "E-post meddelande kunde inte skickas."
|
||||
msgstr ""
|
||||
|
||||
#: erpnext/setup/doctype/employee/employee.py:440
|
||||
msgid "Email is required to create a user"
|
||||
@@ -19001,7 +19001,7 @@ msgstr "Aktivera Tillåt Partiell Reservation i Lager Inställningar för att re
|
||||
#. Booking Settings'
|
||||
#: erpnext/crm/doctype/appointment_booking_settings/appointment_booking_settings.json
|
||||
msgid "Enable Appointment Booking Through Portal"
|
||||
msgstr "Aktivera Tidsbokning via Portal"
|
||||
msgstr ""
|
||||
|
||||
#. Label of the enable_scheduling (Check) field in DocType 'Appointment Booking
|
||||
#. Settings'
|
||||
@@ -23392,7 +23392,7 @@ msgstr "Helg Lista"
|
||||
|
||||
#: erpnext/crm/doctype/appointment_booking_settings/appointment_booking_settings.py:89
|
||||
msgid "Holiday List - {0} is not valid for current date."
|
||||
msgstr "Helgdag Lista - {0} är inte giltig för aktuellt datum."
|
||||
msgstr ""
|
||||
|
||||
#. Label of the holiday_list_name (Data) field in DocType 'Holiday List'
|
||||
#: erpnext/setup/doctype/holiday_list/holiday_list.json
|
||||
@@ -24367,7 +24367,7 @@ msgstr "I Minuter"
|
||||
#. DocType 'Appointment Booking Settings'
|
||||
#: erpnext/crm/doctype/appointment_booking_settings/appointment_booking_settings.json
|
||||
msgid "In Minutes (min: 15 mins, max: 60 mins)"
|
||||
msgstr "I Minuter (min: 15 min, max: 60 min)"
|
||||
msgstr ""
|
||||
|
||||
#: erpnext/accounts/report/accounts_payable/accounts_payable.js:149
|
||||
#: erpnext/accounts/report/accounts_receivable/accounts_receivable.js:181
|
||||
@@ -28030,7 +28030,7 @@ msgstr "Artikel {0} kan inte läggas till som underenhet av sig själv"
|
||||
|
||||
#: erpnext/stock/doctype/material_request/material_request.py:694
|
||||
msgid "Item {0} cannot be ordered more than once"
|
||||
msgstr "Artikel {0} kan inte skapas order för mer än en gång"
|
||||
msgstr ""
|
||||
|
||||
#: erpnext/manufacturing/doctype/blanket_order/blanket_order.py:197
|
||||
msgid "Item {0} cannot be ordered more than {1} against Blanket Order {2}."
|
||||
@@ -30472,7 +30472,7 @@ msgstr "Ange som Stängd "
|
||||
#. in DocType 'Appointment Booking Settings'
|
||||
#: erpnext/crm/doctype/appointment_booking_settings/appointment_booking_settings.json
|
||||
msgid "Mark as Closed"
|
||||
msgstr "Ange som Stängd"
|
||||
msgstr ""
|
||||
|
||||
#. Description of the 'Is Internal Customer' (Check) field in DocType
|
||||
#. 'Customer'
|
||||
@@ -32429,7 +32429,7 @@ msgstr "Ny Försäljning Faktura"
|
||||
#. Credit Limit'
|
||||
#: erpnext/selling/doctype/customer_credit_limit/customer_credit_limit.json
|
||||
msgid "New Sales Invoices are blocked when the customer's overdue amount exceeds this. Requires 'Restrict Customer Over Billing' in Accounts Settings."
|
||||
msgstr "Nya Försäljning Fakturor spärras när kundens förfallna belopp överstiger detta belopp. Erfordrar att alternativ ”Begränsa Kund Överfakturering” är aktiverad i Bokföring Inställningar."
|
||||
msgstr ""
|
||||
|
||||
#. Label of the sales_order (Check) field in DocType 'Email Digest'
|
||||
#: erpnext/setup/doctype/email_digest/email_digest.json
|
||||
@@ -32686,7 +32686,7 @@ msgstr "Inga extra fält tillgängliga"
|
||||
|
||||
#: erpnext/crm/doctype/appointment/appointment.py:103
|
||||
msgid "No availability of slots are found. Please add on Appointment Booking Settings."
|
||||
msgstr "Inga lediga tider hittades. Lägg till detta i Tidsbokning Inställningar."
|
||||
msgstr ""
|
||||
|
||||
#: erpnext/stock/doctype/stock_reservation_entry/stock_reservation_entry.py:1367
|
||||
msgid "No available quantity to reserve for item {0} in warehouse {1}"
|
||||
@@ -34865,15 +34865,15 @@ msgstr "Försening Dagar"
|
||||
#. Credit Limit'
|
||||
#: erpnext/selling/doctype/customer_credit_limit/customer_credit_limit.json
|
||||
msgid "Overdue Limit"
|
||||
msgstr "Förfallen Gräns"
|
||||
msgstr ""
|
||||
|
||||
#: erpnext/selling/doctype/customer/customer.py:707
|
||||
msgid "Overdue Limit Crossed"
|
||||
msgstr "Förfallen Gräns Överskriden"
|
||||
msgstr ""
|
||||
|
||||
#: erpnext/selling/doctype/customer/customer.py:702
|
||||
msgid "Overdue Limit crossed for customer {0}. Overdue amount {1} exceeds the allowed limit {2}."
|
||||
msgstr "Förfallen Gräns överskriden för kund {0}. Förfallen belopp {1} överskrider tillåten gräns {2}."
|
||||
msgstr ""
|
||||
|
||||
#. Name of a DocType
|
||||
#: erpnext/accounts/doctype/overdue_payment/overdue_payment.json
|
||||
@@ -35804,7 +35804,7 @@ msgstr "Delvis Avstämd"
|
||||
#. Option for the 'Status' (Select) field in DocType 'Repost Accounting Ledger'
|
||||
#: erpnext/accounts/doctype/repost_accounting_ledger/repost_accounting_ledger.json
|
||||
msgid "Partially Reposted"
|
||||
msgstr "Delvis Återbokförd"
|
||||
msgstr ""
|
||||
|
||||
#. Option for the 'Status' (Select) field in DocType 'Stock Reservation Entry'
|
||||
#: erpnext/stock/doctype/stock_reservation_entry/stock_reservation_entry.json
|
||||
@@ -36568,7 +36568,7 @@ msgstr "Betalning Gräns"
|
||||
|
||||
#: erpnext/accounts/doctype/payment_request/payment_request.py:434
|
||||
msgid "Payment Link couldn't be sent."
|
||||
msgstr "Betalning Länk kunde inte skickas."
|
||||
msgstr ""
|
||||
|
||||
#: erpnext/accounts/report/pos_register/pos_register.js:50
|
||||
#: erpnext/accounts/report/pos_register/pos_register.py:126
|
||||
@@ -37890,7 +37890,7 @@ msgstr "Lägg till Tillfällig Öppning Konto i Kontoplan"
|
||||
|
||||
#: erpnext/crm/doctype/appointment/appointment.py:95
|
||||
msgid "Please add a valid Holiday List on Appointment Booking Settings."
|
||||
msgstr "Lägg till giltig Helgdag Lista i Tidsbokning Inställningar."
|
||||
msgstr ""
|
||||
|
||||
#: erpnext/accounts/doctype/bank_transaction_rule/bank_transaction_rule.py:119
|
||||
msgid "Please add an account for the Bank Entry rule."
|
||||
@@ -38275,7 +38275,7 @@ msgstr "Fyll i Försäljning Order Tabell"
|
||||
|
||||
#: erpnext/crm/doctype/appointment_booking_settings/appointment_booking_settings.py:57
|
||||
msgid "Please fill up the Availability of Slots table to enable Appointment Scheduling."
|
||||
msgstr "Fyll i tabell ”Lediga Tider” för att aktivera Tidsbokning Schemaläggning."
|
||||
msgstr ""
|
||||
|
||||
#: erpnext/stock/doctype/shipment/shipment.js:277
|
||||
msgid "Please first set Full Name, Email and Phone for the user"
|
||||
@@ -38519,7 +38519,7 @@ msgstr "Välj Försäljning Följesedel"
|
||||
|
||||
#: erpnext/crm/doctype/appointment_booking_settings/appointment_booking_settings.py:81
|
||||
msgid "Please select a Holiday List to enable Appointment Scheduling."
|
||||
msgstr "Välj Helgdag Lista för att aktivera Tidsbokning Schemaläggning."
|
||||
msgstr ""
|
||||
|
||||
#: erpnext/subcontracting/doctype/subcontracting_order/subcontracting_order.py:153
|
||||
msgid "Please select a Subcontracting Purchase Order."
|
||||
@@ -38600,7 +38600,7 @@ msgstr "Välj giltig Inköp Order som är konfigurerad för Underleverantör."
|
||||
|
||||
#: erpnext/accounts/report/accounts_receivable/accounts_receivable.py:1355
|
||||
msgid "Please select a valid {0}"
|
||||
msgstr "Välj giltig {0}"
|
||||
msgstr ""
|
||||
|
||||
#: erpnext/selling/doctype/quotation/quotation.js:245
|
||||
msgid "Please select a value for {0} quotation_to {1}"
|
||||
@@ -42546,12 +42546,12 @@ msgstr "Kvantitet kan inte vara högre än {0} för artikel {1}"
|
||||
|
||||
#: erpnext/stock/doctype/material_request/material_request.py:704
|
||||
msgid "Quantity for Item {0} must be greater than zero and cannot exceed {1}"
|
||||
msgstr "Kvantitet för artikel {0} måste vara högre än noll och får inte överstiga {1}"
|
||||
msgstr ""
|
||||
|
||||
#: erpnext/stock/doctype/material_request/material_request.js:564
|
||||
msgctxt "<b>${pending_qty}</b>"
|
||||
msgid "Quantity for Item {0} must be greater than zero and cannot exceed {1}"
|
||||
msgstr "Kvantitet för artikel {0} måste vara högre än noll och får inte överstiga {1}"
|
||||
msgstr ""
|
||||
|
||||
#: erpnext/subcontracting/doctype/subcontracting_order/subcontracting_order.js:564
|
||||
msgid "Quantity is mandatory for the selected items."
|
||||
@@ -43412,7 +43412,7 @@ msgstr "Räkna om Värdering Pris"
|
||||
|
||||
#: erpnext/stock/doctype/bin/bin.js:10
|
||||
msgid "Recalculate Values"
|
||||
msgstr "Beräkna om Värden"
|
||||
msgstr ""
|
||||
|
||||
#. Option for the 'Status' (Select) field in DocType 'Asset'
|
||||
#. Option for the 'Purpose' (Select) field in DocType 'Asset Movement'
|
||||
@@ -44614,7 +44614,7 @@ msgstr "Bokföring startad i bakgrunden"
|
||||
#. Items'
|
||||
#: erpnext/accounts/doctype/repost_accounting_ledger_items/repost_accounting_ledger_items.json
|
||||
msgid "Reposted"
|
||||
msgstr "Återbokförd"
|
||||
msgstr ""
|
||||
|
||||
#. Label of the reposting_data_file (Attach) field in DocType 'Repost Item
|
||||
#. Valuation'
|
||||
@@ -44642,7 +44642,7 @@ msgstr "Ombokning Referens"
|
||||
#. 'Repost Accounting Ledger Items'
|
||||
#: erpnext/accounts/doctype/repost_accounting_ledger_items/repost_accounting_ledger_items.json
|
||||
msgid "Reposting Status"
|
||||
msgstr "Återbokförd Status"
|
||||
msgstr ""
|
||||
|
||||
#. Label of the vouchers_based_on_item_and_warehouse_section (Section Break)
|
||||
#. field in DocType 'Repost Item Valuation'
|
||||
@@ -44656,11 +44656,11 @@ msgstr "Ombokning av Verifikat Framsteg"
|
||||
|
||||
#: erpnext/accounts/doctype/repost_accounting_ledger/repost_accounting_ledger.py:216
|
||||
msgid "Reposting can be started only for submitted document."
|
||||
msgstr "Återbokföring kan endast påbörjas för godkända dokument."
|
||||
msgstr ""
|
||||
|
||||
#: erpnext/accounts/doctype/repost_accounting_ledger/repost_accounting_ledger.py:221
|
||||
msgid "Reposting cannot be started when status is {0}."
|
||||
msgstr "Återbokföring kan inte påbörjas när status är {0}."
|
||||
msgstr ""
|
||||
|
||||
#: erpnext/stock/report/stock_and_account_value_comparison/stock_and_account_value_comparison.py:227
|
||||
#: erpnext/stock/report/stock_ledger_invariant_check/stock_ledger_invariant_check.py:338
|
||||
@@ -44685,11 +44685,11 @@ msgstr "Ombokning i bakgrund."
|
||||
|
||||
#: erpnext/accounts/doctype/repost_accounting_ledger/repost_accounting_ledger.py:211
|
||||
msgid "Reposting is still in progress in background."
|
||||
msgstr "Återbokföring pågår fortfarande i bakgrunden."
|
||||
msgstr ""
|
||||
|
||||
#: erpnext/accounts/doctype/repost_accounting_ledger/repost_accounting_ledger.py:315
|
||||
msgid "Reposting {0} {1}"
|
||||
msgstr "Återbokför {0} {1}"
|
||||
msgstr ""
|
||||
|
||||
#. Label of the represents_company (Link) field in DocType 'Purchase Invoice'
|
||||
#. Label of the represents_company (Link) field in DocType 'Sales Invoice'
|
||||
@@ -45362,7 +45362,7 @@ msgstr "Begränsa"
|
||||
#. 'Accounts Settings'
|
||||
#: erpnext/accounts/doctype/accounts_settings/accounts_settings.json
|
||||
msgid "Restrict Customer Over Billing"
|
||||
msgstr "Begränsa Kund Överfakturering"
|
||||
msgstr ""
|
||||
|
||||
#. Label of the restrict_based_on (Select) field in DocType 'Party Specific
|
||||
#. Item'
|
||||
@@ -45684,7 +45684,7 @@ msgstr "Omvänd Signatur"
|
||||
|
||||
#: erpnext/accounts/doctype/exchange_rate_revaluation/exchange_rate_revaluation.py:628
|
||||
msgid "Reverse {0} already available in draft status: {1}"
|
||||
msgstr "Omvänd {0} finns redan tillgänglig som utkast: {1}"
|
||||
msgstr ""
|
||||
|
||||
#: erpnext/accounts/doctype/exchange_rate_revaluation/exchange_rate_revaluation.js:118
|
||||
msgid "Reversing Journals..."
|
||||
@@ -45813,7 +45813,7 @@ msgstr "Stav"
|
||||
#. 'Accounts Settings'
|
||||
#: erpnext/accounts/doctype/accounts_settings/accounts_settings.json
|
||||
msgid "Role Allowed to Bypass Over Billing Restriction"
|
||||
msgstr "Roll Tillåten att Kringgå Överfakturering Begränsning"
|
||||
msgstr ""
|
||||
|
||||
#. Label of the role_allowed_to_over_deliver_receive (Link) field in DocType
|
||||
#. 'Stock Settings'
|
||||
@@ -46320,7 +46320,7 @@ msgstr "Rad # #{0}: Avskrivning Start Datum erfordras"
|
||||
|
||||
#: erpnext/accounts/doctype/payment_entry/payment_entry.py:336
|
||||
msgid "Row #{0}: Duplicate entry in References {1} {2}"
|
||||
msgstr "Rad #{0}: Dubblett Post i Referenser {1} {2}"
|
||||
msgstr "Rad # {0}: Duplikat Post i Referenser {1} {2}"
|
||||
|
||||
#: erpnext/selling/doctype/sales_order/sales_order.py:332
|
||||
msgid "Row #{0}: Expected Delivery Date cannot be before Purchase Order Date"
|
||||
@@ -48525,7 +48525,7 @@ msgstr "Schemaläggare är inaktiv. Kan inte slå samman konton."
|
||||
|
||||
#: erpnext/accounts/doctype/repost_accounting_ledger/repost_accounting_ledger.py:232
|
||||
msgid "Scheduler is inactive. Reposting will only run once background jobs are processed."
|
||||
msgstr "Schemaläggare är inaktiv. Återbokföring kommer endast att köras när bakgrundsjobb är klara."
|
||||
msgstr ""
|
||||
|
||||
#. Label of the schedules (Table) field in DocType 'Maintenance Schedule'
|
||||
#: erpnext/maintenance/doctype/maintenance_schedule/maintenance_schedule.json
|
||||
@@ -48958,7 +48958,7 @@ msgstr "Välj Leverantör Adress"
|
||||
|
||||
#: erpnext/stock/doctype/material_request/material_request.js:448
|
||||
msgid "Select Supplier for Items"
|
||||
msgstr "Välj Leverantör för Artiklar"
|
||||
msgstr ""
|
||||
|
||||
#: erpnext/stock/doctype/batch/batch.js:150
|
||||
msgid "Select Target Warehouse"
|
||||
@@ -49012,7 +49012,7 @@ msgstr "Välj Leverantör"
|
||||
#: erpnext/stock/doctype/material_request/material_request.js:552
|
||||
#: erpnext/stock/doctype/material_request/material_request.py:699
|
||||
msgid "Select a Supplier for Item {0}"
|
||||
msgstr "Välj Leverantör för Artikel {0}"
|
||||
msgstr ""
|
||||
|
||||
#: banking/src/components/features/BankReconciliation/MatchAndReconcile.tsx:49
|
||||
msgid "Select a bank account to reconcile"
|
||||
@@ -49053,7 +49053,7 @@ msgstr "Välj artikel från varje uppsättning som ska användas i Försäljning
|
||||
#: erpnext/stock/doctype/material_request/material_request.js:539
|
||||
#: erpnext/stock/doctype/material_request/material_request.py:680
|
||||
msgid "Select at least one Item"
|
||||
msgstr "Välj minst en artikel"
|
||||
msgstr ""
|
||||
|
||||
#: erpnext/stock/doctype/item/item.js:944
|
||||
msgid "Select at least one attribute value."
|
||||
@@ -49372,7 +49372,7 @@ msgstr "Skicka med Bilaga"
|
||||
#: erpnext/accounts/doctype/payment_request/payment_request.js:51
|
||||
#: erpnext/accounts/doctype/payment_request/payment_request.js:55
|
||||
msgid "Sending Email"
|
||||
msgstr "Skickar e-post"
|
||||
msgstr ""
|
||||
|
||||
#. Option for the 'Detected Amount Format' (Select) field in DocType 'Bank
|
||||
#. Statement Import Log'
|
||||
@@ -50201,7 +50201,7 @@ msgstr "Ange Leverantör"
|
||||
|
||||
#: erpnext/stock/doctype/material_request/material_request.js:455
|
||||
msgid "Set Supplier for All Items"
|
||||
msgstr "Ange Leverantör för Alla Artiklar"
|
||||
msgstr ""
|
||||
|
||||
#. Label of the set_target_warehouse (Link) field in DocType 'Sales Invoice'
|
||||
#. Label of the set_warehouse (Link) field in DocType 'Purchase Order'
|
||||
@@ -52616,7 +52616,7 @@ msgstr "Lager ej tillgängligt för Artikel {0} i Lager {1}."
|
||||
|
||||
#: erpnext/stock/doctype/stock_reservation_entry/stock_reservation_entry.py:1240
|
||||
msgid "Stock not available to reserve for the Item {0} in Warehouse {1}."
|
||||
msgstr "Lager är inte tillgängligt för reservation för artikel {0} i lager {1}."
|
||||
msgstr ""
|
||||
|
||||
#: erpnext/selling/page/point_of_sale/pos_controller.js:826
|
||||
msgid "Stock quantity not enough for Item Code: {0} under warehouse {1}. Available quantity {2} {3}."
|
||||
@@ -55293,7 +55293,7 @@ msgstr "Konto under Skuld eller Eget Kapital, där Resultat Bokförs"
|
||||
|
||||
#: erpnext/accounts/doctype/account/account.py:222
|
||||
msgid "The account type of {0} cannot be changed from {1} because stock ledger entries exist against it."
|
||||
msgstr "Konto typ {0} kan inte ändras från {1} eftersom det finns lager poster mot den."
|
||||
msgstr ""
|
||||
|
||||
#: erpnext/accounts/doctype/payment_request/payment_request.py:1016
|
||||
msgid "The allocated amount is greater than the outstanding amount of Payment Request {0}"
|
||||
@@ -55451,7 +55451,7 @@ msgstr "Följande rader är dubbletter:"
|
||||
|
||||
#: erpnext/accounts/doctype/repost_accounting_ledger/repost_accounting_ledger.py:130
|
||||
msgid "The following vouchers are not submitted: {0}"
|
||||
msgstr "Följande verifikationer är inte godkända: {0}"
|
||||
msgstr ""
|
||||
|
||||
#: erpnext/stock/doctype/material_request/material_request.py:1062
|
||||
msgid "The following {0} were created: {1}"
|
||||
@@ -55963,7 +55963,7 @@ msgstr "Detta dokument är över gräns med {0} {1} för post {4}. Skapa annan {
|
||||
|
||||
#: erpnext/templates/emails/appointment_confirmed.html:6
|
||||
msgid "This email was sent from {0}"
|
||||
msgstr "Detta e-postmeddelande skickades från {0}"
|
||||
msgstr ""
|
||||
|
||||
#: erpnext/stock/doctype/delivery_note/delivery_note.js:496
|
||||
msgid "This field is used to set the 'Customer'."
|
||||
@@ -56109,7 +56109,7 @@ msgstr "Detta artikel filter har redan tillämpats för {0}"
|
||||
|
||||
#: erpnext/templates/emails/confirm_appointment.html:4
|
||||
msgid "This link is valid for {0} minutes"
|
||||
msgstr "Denna länk är giltig i {0} minuter"
|
||||
msgstr ""
|
||||
|
||||
#: erpnext/www/banking.py:35
|
||||
msgid "This method is only meant for developer mode"
|
||||
@@ -56230,7 +56230,7 @@ msgstr "Detta värde ska användas när ingen matchande Gemensam Kod för post h
|
||||
|
||||
#: erpnext/www/book_appointment/verify/index.py:18
|
||||
msgid "This verification link is invalid. Please book the appointment again."
|
||||
msgstr "Denna verifiering länk är ogiltig. Boka ny tid."
|
||||
msgstr ""
|
||||
|
||||
#: banking/src/components/features/Settings/Preferences.tsx:86
|
||||
msgid "This will automatically run transaction matching rules on unreconciled transactions every hour."
|
||||
@@ -58037,7 +58037,7 @@ msgstr "Transaktioner mot bolag finns redan! Kontoplan kan endast importeras fö
|
||||
#. 'Customer'
|
||||
#: erpnext/selling/doctype/customer/customer.json
|
||||
msgid "Transactions are blocked when the outstanding balance exceeds the credit limit. When Restrict Customer Over Billing is enabled, new invoices are also blocked when the customer's overdue amount exceeds the Overdue Limit."
|
||||
msgstr "Transaktioner blockeras när det utestående saldo överskrider kredit gräns. När funktion ”Begränsa Kund Överfakturering” är aktiverad blockeras även nya fakturor när kundens förfallna belopp överskrider gräns för förfallna fordringar."
|
||||
msgstr ""
|
||||
|
||||
#: banking/src/components/features/BankStatementImporter/CSV/StatementDetails.tsx:239
|
||||
msgid "Transactions to be imported into the system"
|
||||
@@ -58658,7 +58658,7 @@ msgstr "Ångra Tilldelningar"
|
||||
|
||||
#: erpnext/accounts/doctype/repost_accounting_ledger/repost_accounting_ledger.py:375
|
||||
msgid "Unable to Repost Accounting Ledger"
|
||||
msgstr "Kunde inte Återbokföra Bokföring Register"
|
||||
msgstr ""
|
||||
|
||||
#: erpnext/setup/doctype/transaction_deletion_record/transaction_deletion_record.py:477
|
||||
msgid "Unable to fetch DocType details. Please contact system administrator."
|
||||
@@ -59601,7 +59601,7 @@ msgstr "Användare med denna roll tillåts att överleverera/ta emot ordrar öve
|
||||
#. field in DocType 'Accounts Settings'
|
||||
#: erpnext/accounts/doctype/accounts_settings/accounts_settings.json
|
||||
msgid "Users with this role can still submit invoices for customers who have crossed their Overdue Limit."
|
||||
msgstr "Användare med denna roll kan fortfarande godkänna fakturor för kunder som överskridit överfakturering gräns."
|
||||
msgstr ""
|
||||
|
||||
#. Description of the 'Role to Notify on Depreciation Failure' (Link) field in
|
||||
#. DocType 'Accounts Settings'
|
||||
@@ -60148,12 +60148,12 @@ msgstr "Risk Kapital"
|
||||
#. 'Appointment Booking Settings'
|
||||
#: erpnext/crm/doctype/appointment_booking_settings/appointment_booking_settings.json
|
||||
msgid "Verification Link Expiry Duration"
|
||||
msgstr "Verifiering Länk Utgångstid"
|
||||
msgstr ""
|
||||
|
||||
#. Label of the verification_token (Data) field in DocType 'Appointment'
|
||||
#: erpnext/crm/doctype/appointment/appointment.json
|
||||
msgid "Verification Token"
|
||||
msgstr "Verifiering Kod"
|
||||
msgstr ""
|
||||
|
||||
#: erpnext/www/book_appointment/verify/index.html:15
|
||||
msgid "Verification failed please check the link"
|
||||
@@ -60161,7 +60161,7 @@ msgstr "Verifiering misslyckades, kontrollera länk"
|
||||
|
||||
#: erpnext/www/book_appointment/verify/index.py:38
|
||||
msgid "Verification link has expired."
|
||||
msgstr "Verifiering Länk har upphört."
|
||||
msgstr ""
|
||||
|
||||
#. Label of the verified_by (Data) field in DocType 'Quality Inspection'
|
||||
#: erpnext/stock/doctype/quality_inspection/quality_inspection.json
|
||||
@@ -61019,7 +61019,7 @@ msgstr "Vi kan se att {0} görs mot {1}. Om du vill att {1} s utestående ska up
|
||||
|
||||
#: erpnext/templates/emails/appointment_confirmed.html:3
|
||||
msgid "We look forward to meeting you"
|
||||
msgstr "Vi ser fram emot att träffa dig"
|
||||
msgstr ""
|
||||
|
||||
#: banking/src/pages/BankStatementImporter.tsx:169
|
||||
msgid "We support uploading CSV, XLSX, XLS and PDF files. Please make sure the file contains the correct columns."
|
||||
@@ -62130,7 +62130,7 @@ msgstr "Ditt Namn"
|
||||
|
||||
#: erpnext/templates/emails/appointment_confirmed.html:2
|
||||
msgid "Your email has been verified and your appointment has been confirmed for {0}"
|
||||
msgstr "Din e-post adress har verifierats och bokad tid har bekräftats för {0}"
|
||||
msgstr ""
|
||||
|
||||
#: erpnext/www/book_appointment/verify/index.html:11
|
||||
msgid "Your email has been verified and your appointment has been scheduled"
|
||||
@@ -62955,7 +62955,7 @@ msgstr "{0} vy stöds för närvarande inte i Anpassad Bokslut Rapport."
|
||||
|
||||
#: erpnext/stock/doctype/material_request/material_request.py:732
|
||||
msgid "{0} was set to today for items whose requested date has passed"
|
||||
msgstr "{0} angavs till idag för artiklar vars begärda datum har passerat"
|
||||
msgstr ""
|
||||
|
||||
#: erpnext/accounts/doctype/payment_term/payment_term.js:19
|
||||
msgid "{0} will be given as discount."
|
||||
|
||||
@@ -881,15 +881,10 @@ def reset_item_valuation_rate(item_code, warehouse_list=None, qty=None, rate=Non
|
||||
warehouse_list = [warehouse_list]
|
||||
|
||||
if not warehouse_list:
|
||||
# Reconcile every warehouse the item has a non-zero balance in -- including
|
||||
# negative balances left by other tests. get_valuation_rate averages
|
||||
# Sum(stock_value)/Sum(actual_qty) across all bins, so a leftover negative
|
||||
# balance in one warehouse can cancel the reset qty elsewhere and make the
|
||||
# average collapse to 0, which is a source of flaky BOM-cost failures.
|
||||
warehouse_list = frappe.db.sql_list(
|
||||
"""
|
||||
select warehouse from `tabBin`
|
||||
where item_code=%s and actual_qty != 0
|
||||
where item_code=%s and actual_qty > 0
|
||||
""",
|
||||
item_code,
|
||||
)
|
||||
|
||||
@@ -159,9 +159,6 @@ class DeprecatedBatchNoValuation:
|
||||
if self.sle.name:
|
||||
query = query.where(sle.name != self.sle.name)
|
||||
|
||||
if getattr(self, "stock_closing_from_datetime", None):
|
||||
query = query.where(sle.posting_datetime >= self.stock_closing_from_datetime)
|
||||
|
||||
return query.run(as_dict=True)
|
||||
|
||||
@deprecated(
|
||||
|
||||
@@ -533,7 +533,7 @@ frappe.ui.form.on("Material Request", {
|
||||
},
|
||||
],
|
||||
primary_action_label: __("Create"),
|
||||
primary_action: function (values) {
|
||||
primary_action: async function (values) {
|
||||
const item_suppliers = (values.items || []).filter((row) => row.__checked);
|
||||
if (!item_suppliers.length) {
|
||||
frappe.throw(__("Select at least one Item"));
|
||||
@@ -567,6 +567,10 @@ frappe.ui.form.on("Material Request", {
|
||||
);
|
||||
}
|
||||
|
||||
if (!(await erpnext.utils.confirm_if_drafts_exist(frm.doc, "Purchase Order"))) {
|
||||
return;
|
||||
}
|
||||
|
||||
frappe.call({
|
||||
method: "erpnext.stock.doctype.material_request.material_request.make_purchase_orders_by_supplier",
|
||||
args: { source_name: frm.doc.name, item_suppliers: item_suppliers },
|
||||
|
||||
@@ -5611,66 +5611,6 @@ class TestPurchaseReceipt(ERPNextTestSuite):
|
||||
|
||||
self.assertEqual(frappe.parse_json(stock_queue), [[20, 0.0]])
|
||||
|
||||
def test_purchase_return_valuation_for_batchwise_valuation_batch(self):
|
||||
from erpnext.controllers.sales_and_purchase_return import make_return_doc
|
||||
from erpnext.stock.doctype.delivery_note.test_delivery_note import create_delivery_note
|
||||
|
||||
item_code = make_item(
|
||||
"Test Purchase Return Batchwise Valn Item",
|
||||
{
|
||||
"is_stock_item": 1,
|
||||
"has_batch_no": 1,
|
||||
"batch_number_series": "BN-TPRBWV-.#####",
|
||||
},
|
||||
).name
|
||||
|
||||
batch_no = "BN-TPRBWV-00001"
|
||||
batch = frappe.new_doc("Batch").update({"batch_id": batch_no, "item": item_code}).insert()
|
||||
self.assertEqual(batch.use_batchwise_valuation, 1)
|
||||
|
||||
warehouse = "_Test Warehouse - _TC"
|
||||
pr = make_purchase_receipt(
|
||||
item_code=item_code,
|
||||
qty=100,
|
||||
rate=1000,
|
||||
warehouse=warehouse,
|
||||
batch_no=batch_no,
|
||||
use_serial_batch_fields=1,
|
||||
)
|
||||
make_purchase_receipt(
|
||||
item_code=item_code,
|
||||
qty=100,
|
||||
rate=400,
|
||||
warehouse=warehouse,
|
||||
batch_no=batch_no,
|
||||
use_serial_batch_fields=1,
|
||||
)
|
||||
create_delivery_note(
|
||||
item_code=item_code,
|
||||
qty=100,
|
||||
warehouse=warehouse,
|
||||
batch_no=batch_no,
|
||||
use_serial_batch_fields=1,
|
||||
)
|
||||
|
||||
return_pr = make_return_doc("Purchase Receipt", pr.name)
|
||||
return_pr.submit()
|
||||
|
||||
sle = frappe.db.get_value(
|
||||
"Stock Ledger Entry",
|
||||
{"voucher_no": return_pr.name, "is_cancelled": 0},
|
||||
["stock_value_difference", "qty_after_transaction", "stock_value", "serial_and_batch_bundle"],
|
||||
as_dict=True,
|
||||
)
|
||||
self.assertEqual(flt(sle.qty_after_transaction), 0.0)
|
||||
self.assertEqual(flt(sle.stock_value_difference, 2), -70000.0)
|
||||
self.assertEqual(flt(sle.stock_value, 2), 0.0)
|
||||
|
||||
rate = frappe.db.get_value(
|
||||
"Serial and Batch Entry", {"parent": sle.serial_and_batch_bundle}, "incoming_rate"
|
||||
)
|
||||
self.assertEqual(flt(rate, 2), 700.0)
|
||||
|
||||
def test_negative_stock_error_for_purchase_return(self):
|
||||
from erpnext.controllers.sales_and_purchase_return import make_return_doc
|
||||
from erpnext.stock.doctype.stock_entry.test_stock_entry import make_stock_entry
|
||||
|
||||
@@ -414,13 +414,6 @@ class SerialandBatchBundle(Document):
|
||||
|
||||
valuation_method = get_valuation_method(self.item_code, self.company)
|
||||
|
||||
# An outward return must go out at the batch's current average rate for a
|
||||
# batchwise valuation batch. The original receipt rate is only correct while
|
||||
# the batch still holds stock at that rate; once other receipts have changed
|
||||
# the average, removing at the original rate strands a residue in the batch
|
||||
# value (negative when returning the costlier receipt).
|
||||
batchwise_avg_rates = self.get_batchwise_return_avg_rates()
|
||||
|
||||
stock_queue = []
|
||||
non_batchwise_batches = []
|
||||
if not self.has_serial_no and valuation_method == "FIFO":
|
||||
@@ -454,12 +447,6 @@ class SerialandBatchBundle(Document):
|
||||
batches = sorted(list(valuation_details["batches"].keys()))
|
||||
valuation_rate = valuation_details["batches"].get(batches[cint(row.idx) - 1])
|
||||
|
||||
# a batch with an available balance goes out at its current average rate (a
|
||||
# valid 0.0 included); the original receipt rate applies only when there is
|
||||
# no balance to average
|
||||
if not row.serial_no and row.batch_no in batchwise_avg_rates:
|
||||
valuation_rate = batchwise_avg_rates[row.batch_no]
|
||||
|
||||
row.incoming_rate = flt(valuation_rate)
|
||||
row.stock_value_difference = flt(row.qty) * flt(row.incoming_rate)
|
||||
|
||||
@@ -488,43 +475,6 @@ class SerialandBatchBundle(Document):
|
||||
elif self.type_of_transaction == "Inward":
|
||||
self.set_incoming_rate_for_inward_transaction(row, save, prev_sle=prev_sle)
|
||||
|
||||
def get_batchwise_return_avg_rates(self):
|
||||
from erpnext.stock.utils import get_valuation_method
|
||||
|
||||
if self.type_of_transaction != "Outward" or self.has_serial_no:
|
||||
return {}
|
||||
|
||||
batch_nos = [d.batch_no for d in self.entries if d.batch_no]
|
||||
if not batch_nos:
|
||||
return {}
|
||||
|
||||
if get_valuation_method(
|
||||
self.item_code, self.company
|
||||
) == "Moving Average" and frappe.db.get_single_value(
|
||||
"Stock Settings", "do_not_use_batchwise_valuation"
|
||||
):
|
||||
return {}
|
||||
|
||||
batchwise_batches = frappe.get_all(
|
||||
"Batch",
|
||||
filters={"name": ("in", batch_nos), "use_batchwise_valuation": 1},
|
||||
pluck="name",
|
||||
)
|
||||
if not batchwise_batches:
|
||||
return {}
|
||||
|
||||
# scoped to batchwise batches only, so BatchNoValuation's non-batchwise
|
||||
# machinery never runs for them
|
||||
sle = self.get_sle_for_outward_transaction()
|
||||
sle.batch_nos = {batch_no: sle.batch_nos[batch_no] for batch_no in batchwise_batches}
|
||||
sle.batchwise_valuation_batches = batchwise_batches
|
||||
sn_obj = BatchNoValuation(sle=sle, item_code=self.item_code, warehouse=self.warehouse)
|
||||
return {
|
||||
batch_no: abs(flt(sn_obj.batch_avg_rate.get(batch_no)))
|
||||
for batch_no in batchwise_batches
|
||||
if flt(sn_obj.available_qty.get(batch_no))
|
||||
}
|
||||
|
||||
def validate_returned_serial_batch_no(self, return_against, row, original_inv_details):
|
||||
if frappe.flags.through_repost_item_valuation and not frappe.in_test:
|
||||
return
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
import json
|
||||
|
||||
import frappe
|
||||
from frappe.utils import add_days, add_to_date, flt, nowtime, today
|
||||
from frappe.utils import flt, nowtime, today
|
||||
|
||||
from erpnext.stock.doctype.item.test_item import make_item
|
||||
from erpnext.stock.doctype.serial_and_batch_bundle.serial_and_batch_bundle import (
|
||||
@@ -1601,190 +1601,3 @@ class TestSerialandBatchBundleLogic(ERPNextTestSuite):
|
||||
|
||||
self.assertNotIn(bundles[1], bundle_wise_serial_nos)
|
||||
self.assertEqual(bundle_wise_serial_nos[bundles[0]], [serial_no])
|
||||
|
||||
@ERPNextTestSuite.change_settings(
|
||||
"Stock Settings", {"auto_create_serial_and_batch_bundle_for_outward": 1}
|
||||
)
|
||||
def test_batchwise_valuation_for_same_posting_datetime_entries(self):
|
||||
# an inward at a different rate and multiple outward rows with the same
|
||||
# item and warehouse share the same posting datetime, the tie-breaking
|
||||
# must include the same-timestamp entries which are already part of the
|
||||
# ledger and must not let the outward rows count each other
|
||||
item_code = make_item(
|
||||
"Test Batchwise Same Posting Datetime Item 1",
|
||||
properties={
|
||||
"is_stock_item": 1,
|
||||
"has_batch_no": 1,
|
||||
"create_new_batch": 1,
|
||||
"batch_number_series": "TBSPD-ITEM1-.#####",
|
||||
"valuation_method": "FIFO",
|
||||
},
|
||||
).name
|
||||
|
||||
warehouse = "_Test Warehouse - _TC"
|
||||
|
||||
receipt = make_stock_entry(
|
||||
item_code=item_code,
|
||||
qty=10,
|
||||
rate=100,
|
||||
target=warehouse,
|
||||
posting_date=add_days(today(), -5),
|
||||
posting_time="12:00:00",
|
||||
)
|
||||
|
||||
batch_no = get_batch_from_bundle(receipt.items[0].serial_and_batch_bundle)
|
||||
self.assertTrue(frappe.db.get_value("Batch", batch_no, "use_batchwise_valuation"))
|
||||
|
||||
# same posting datetime as the outward rows below, at a different rate
|
||||
make_stock_entry(
|
||||
item_code=item_code,
|
||||
qty=20,
|
||||
rate=250,
|
||||
target=warehouse,
|
||||
batch_no=batch_no,
|
||||
use_serial_batch_fields=1,
|
||||
posting_date=add_days(today(), -3),
|
||||
posting_time="12:00:00",
|
||||
)
|
||||
|
||||
issue = make_stock_entry(
|
||||
item_code=item_code,
|
||||
qty=2,
|
||||
source=warehouse,
|
||||
posting_date=add_days(today(), -3),
|
||||
posting_time="12:00:00",
|
||||
do_not_save=True,
|
||||
)
|
||||
|
||||
for qty in [3, 4]:
|
||||
issue.append(
|
||||
"items",
|
||||
{
|
||||
"item_code": item_code,
|
||||
"s_warehouse": warehouse,
|
||||
"qty": qty,
|
||||
"conversion_factor": 1,
|
||||
},
|
||||
)
|
||||
|
||||
issue.save()
|
||||
issue.submit()
|
||||
|
||||
# (10 * 100 + 20 * 250) / 30 = 200
|
||||
self.assert_batchwise_outgoing_rate(item_code, outgoing_rate=200.0, balance_value=4200.0)
|
||||
|
||||
# backdated receipt reposts the same posting datetime cluster
|
||||
make_stock_entry(
|
||||
item_code=item_code,
|
||||
qty=10,
|
||||
rate=100,
|
||||
target=warehouse,
|
||||
batch_no=batch_no,
|
||||
use_serial_batch_fields=1,
|
||||
posting_date=add_days(today(), -4),
|
||||
posting_time="12:00:00",
|
||||
)
|
||||
|
||||
# (20 * 100 + 20 * 250) / 40 = 175
|
||||
self.assert_batchwise_outgoing_rate(item_code, outgoing_rate=175.0, balance_value=5425.0)
|
||||
|
||||
@ERPNextTestSuite.change_settings(
|
||||
"Stock Settings", {"auto_create_serial_and_batch_bundle_for_outward": 1}
|
||||
)
|
||||
def test_batchwise_valuation_when_bundle_created_before_the_sle(self):
|
||||
# a bundle can be created (drafted) much before / after its SLE, the
|
||||
# tie-breaking for the same posting datetime entries must follow the
|
||||
# SLE creation and not the bundle creation
|
||||
item_code = make_item(
|
||||
"Test Batchwise Same Posting Datetime Item 2",
|
||||
properties={
|
||||
"is_stock_item": 1,
|
||||
"has_batch_no": 1,
|
||||
"create_new_batch": 1,
|
||||
"batch_number_series": "TBSPD-ITEM2-.#####",
|
||||
"valuation_method": "FIFO",
|
||||
},
|
||||
).name
|
||||
|
||||
warehouse = "_Test Warehouse - _TC"
|
||||
|
||||
receipt = make_stock_entry(
|
||||
item_code=item_code,
|
||||
qty=10,
|
||||
rate=100,
|
||||
target=warehouse,
|
||||
posting_date=add_days(today(), -5),
|
||||
posting_time="12:00:00",
|
||||
)
|
||||
|
||||
batch_no = get_batch_from_bundle(receipt.items[0].serial_and_batch_bundle)
|
||||
|
||||
# inward at a different rate, same posting datetime as the outward below
|
||||
inward = make_stock_entry(
|
||||
item_code=item_code,
|
||||
qty=10,
|
||||
rate=200,
|
||||
target=warehouse,
|
||||
batch_no=batch_no,
|
||||
use_serial_batch_fields=1,
|
||||
posting_date=add_days(today(), -3),
|
||||
posting_time="12:00:00",
|
||||
)
|
||||
|
||||
outward = make_stock_entry(
|
||||
item_code=item_code,
|
||||
qty=10,
|
||||
source=warehouse,
|
||||
posting_date=add_days(today(), -3),
|
||||
posting_time="12:00:00",
|
||||
)
|
||||
|
||||
# simulate the inward's bundle drafted after the outward's SLE, the
|
||||
# bundle creation timeline no longer matches the SLE creation timeline
|
||||
outward_sle_creation = frappe.db.get_value(
|
||||
"Stock Ledger Entry",
|
||||
{"voucher_no": outward.name, "is_cancelled": 0},
|
||||
"creation",
|
||||
)
|
||||
|
||||
frappe.db.set_value(
|
||||
"Serial and Batch Bundle",
|
||||
inward.items[0].serial_and_batch_bundle,
|
||||
"creation",
|
||||
add_to_date(outward_sle_creation, minutes=30),
|
||||
update_modified=False,
|
||||
)
|
||||
|
||||
repost = frappe.get_doc(
|
||||
{
|
||||
"doctype": "Repost Item Valuation",
|
||||
"based_on": "Item and Warehouse",
|
||||
"item_code": item_code,
|
||||
"warehouse": warehouse,
|
||||
"posting_date": add_days(today(), -6),
|
||||
"posting_time": "00:00:00",
|
||||
"allow_negative_stock": 1,
|
||||
}
|
||||
)
|
||||
|
||||
repost.submit()
|
||||
|
||||
# (10 * 100 + 10 * 200) / 20 = 150, the inward precedes the outward as
|
||||
# per the SLE creation even though its bundle was created afterwards
|
||||
self.assert_batchwise_outgoing_rate(item_code, outgoing_rate=150.0, balance_value=1500.0)
|
||||
|
||||
def assert_batchwise_outgoing_rate(self, item_code, outgoing_rate, balance_value):
|
||||
sl_entries = frappe.get_all(
|
||||
"Stock Ledger Entry",
|
||||
filters={"item_code": item_code, "is_cancelled": 0},
|
||||
fields=["actual_qty", "stock_value_difference", "stock_value"],
|
||||
order_by="posting_datetime, creation",
|
||||
)
|
||||
|
||||
for sle in sl_entries:
|
||||
if sle.actual_qty > 0:
|
||||
continue
|
||||
|
||||
self.assertEqual(flt(sle.stock_value_difference, 2), flt(sle.actual_qty * outgoing_rate, 2))
|
||||
|
||||
self.assertEqual(flt(sl_entries[-1].stock_value, 2), flt(balance_value, 2))
|
||||
|
||||
@@ -10,51 +10,9 @@ from frappe.desk.form.load import get_attachments
|
||||
from frappe.model.document import Document
|
||||
from frappe.utils import add_days, get_date_str, get_link_to_form, nowtime, parse_json
|
||||
from frappe.utils.background_jobs import enqueue
|
||||
from frappe.utils.caching import request_cache
|
||||
|
||||
from erpnext.stock.doctype.inventory_dimension.inventory_dimension import get_inventory_dimensions
|
||||
|
||||
SCOPE_FIELDS = ("warehouse", "item_code", "item_group", "warehouse_type")
|
||||
|
||||
|
||||
def apply_unscoped_filters(filters):
|
||||
meta = frappe.get_meta("Stock Closing Entry")
|
||||
for fieldname in SCOPE_FIELDS:
|
||||
if meta.has_field(fieldname):
|
||||
filters[fieldname] = ("is", "not set")
|
||||
|
||||
return filters
|
||||
|
||||
|
||||
def get_closing_entry_for_closed_period(company):
|
||||
closed_upto = frappe.db.get_value(
|
||||
"Period Closing Voucher", {"docstatus": 1, "company": company}, [{"MAX": "period_end_date"}]
|
||||
)
|
||||
if not closed_upto:
|
||||
return None
|
||||
|
||||
return _get_completed_closing_entry(company, str(closed_upto))
|
||||
|
||||
|
||||
@request_cache
|
||||
def _get_completed_closing_entry(company, closed_upto):
|
||||
filters = apply_unscoped_filters(
|
||||
{
|
||||
"company": company,
|
||||
"docstatus": 1,
|
||||
"status": "Completed",
|
||||
"to_date": ("<=", closed_upto),
|
||||
}
|
||||
)
|
||||
|
||||
return frappe.db.get_value(
|
||||
"Stock Closing Entry",
|
||||
filters,
|
||||
["name", "to_date"],
|
||||
order_by="to_date desc",
|
||||
as_dict=True,
|
||||
)
|
||||
|
||||
|
||||
class StockClosingEntry(Document):
|
||||
# begin: auto-generated types
|
||||
@@ -110,7 +68,7 @@ class StockClosingEntry(Document):
|
||||
)
|
||||
)
|
||||
|
||||
for fieldname in SCOPE_FIELDS:
|
||||
for fieldname in ["warehouse", "item_code", "item_group", "warehouse_type"]:
|
||||
if self.get(fieldname):
|
||||
query = query.where(table[fieldname] == self.get(fieldname))
|
||||
|
||||
@@ -128,30 +86,14 @@ class StockClosingEntry(Document):
|
||||
self.enqueue_job()
|
||||
|
||||
def on_cancel(self):
|
||||
self.validate_closed_period_lock()
|
||||
self.set_status(save=True)
|
||||
self.remove_stock_closing()
|
||||
|
||||
def validate_closed_period_lock(self):
|
||||
pcv = frappe.db.get_value(
|
||||
"Period Closing Voucher",
|
||||
{"company": self.company, "docstatus": 1, "period_end_date": (">=", self.to_date)},
|
||||
"name",
|
||||
)
|
||||
|
||||
if pcv:
|
||||
frappe.throw(
|
||||
_(
|
||||
"Stock Closing Entry {0} belongs to a closed accounting period. Cancel the Period Closing Voucher {1} first."
|
||||
).format(self.name, get_link_to_form("Period Closing Voucher", pcv)),
|
||||
title=_("Closed Period"),
|
||||
)
|
||||
|
||||
def remove_stock_closing(self):
|
||||
table = frappe.qb.DocType("Stock Closing Balance")
|
||||
frappe.qb.from_(table).delete().where(table.stock_closing_entry == self.name).run()
|
||||
|
||||
@frappe.whitelist(methods=["POST"])
|
||||
@frappe.whitelist()
|
||||
def enqueue_job(self):
|
||||
self.db_set("status", "In Progress")
|
||||
enqueue(prepare_closing_stock_balance, name=self.name, queue="long", timeout=1500)
|
||||
@@ -161,9 +103,8 @@ class StockClosingEntry(Document):
|
||||
).format(self.name)
|
||||
)
|
||||
|
||||
@frappe.whitelist(methods=["POST"])
|
||||
@frappe.whitelist()
|
||||
def regenerate_closing_balance(self):
|
||||
self.validate_closed_period_lock()
|
||||
self.remove_stock_closing()
|
||||
self.enqueue_job()
|
||||
|
||||
|
||||
@@ -7,10 +7,8 @@ from collections import defaultdict
|
||||
|
||||
import frappe
|
||||
from frappe import _
|
||||
from frappe.query_builder.functions import IfNull, Sum
|
||||
from frappe.query_builder.functions import Sum
|
||||
from frappe.utils import cint, flt, get_datetime
|
||||
from pypika import Order
|
||||
from pypika.analytics import RowNumber
|
||||
|
||||
from erpnext.stock.doctype.inventory_dimension.inventory_dimension import get_inventory_dimensions
|
||||
from erpnext.stock.doctype.serial_no.serial_no import get_serial_nos
|
||||
@@ -55,15 +53,14 @@ def execute(filters=None):
|
||||
|
||||
data = []
|
||||
conversion_factors = []
|
||||
opening_rows = opening_row if isinstance(opening_row, list) else ([opening_row] if opening_row else [])
|
||||
for row in opening_rows:
|
||||
data.append(row)
|
||||
if opening_row:
|
||||
data.append(opening_row)
|
||||
conversion_factors.append(0)
|
||||
|
||||
actual_qty = stock_value = 0
|
||||
if opening_rows:
|
||||
actual_qty = opening_rows[0].get("qty_after_transaction", 0)
|
||||
stock_value = opening_rows[0].get("stock_value", 0)
|
||||
if opening_row:
|
||||
actual_qty = opening_row.get("qty_after_transaction")
|
||||
stock_value = opening_row.get("stock_value")
|
||||
|
||||
available_serial_nos = {}
|
||||
|
||||
@@ -696,120 +693,43 @@ def get_opening_balance(filters, columns, sl_entries, inv_dimension_wise_value=N
|
||||
if not (filters.item_code and filters.warehouse and filters.from_date):
|
||||
return
|
||||
|
||||
item_codes = filters.item_code
|
||||
if isinstance(item_codes, str):
|
||||
item_codes = [item_codes]
|
||||
from erpnext.stock.stock_ledger import get_previous_sle
|
||||
|
||||
warehouses = get_matching_warehouses(filters.warehouse)
|
||||
if not warehouses:
|
||||
return
|
||||
project = None
|
||||
if filters.get("project") and not frappe.get_all(
|
||||
"Inventory Dimension", filters={"reference_document": "Project"}
|
||||
):
|
||||
project = filters.get("project")
|
||||
|
||||
sle_doctype = frappe.qb.DocType("Stock Ledger Entry")
|
||||
sr_doctype = frappe.qb.DocType("Stock Reconciliation")
|
||||
|
||||
opening_reco_query = (
|
||||
frappe.qb.from_(sle_doctype)
|
||||
.inner_join(sr_doctype)
|
||||
.on(sle_doctype.voucher_no == sr_doctype.name)
|
||||
.select(sle_doctype.voucher_no)
|
||||
.where(sle_doctype.docstatus < 2)
|
||||
.where(sle_doctype.is_cancelled == 0)
|
||||
.where(sle_doctype.item_code.isin(item_codes))
|
||||
.where(sle_doctype.warehouse.isin(warehouses))
|
||||
.where(sle_doctype.voucher_type == "Stock Reconciliation")
|
||||
.where(sle_doctype.posting_date == filters.from_date)
|
||||
.where(sr_doctype.purpose == "Opening Stock")
|
||||
last_entry = get_previous_sle(
|
||||
{
|
||||
"item_code": filters.item_code,
|
||||
"warehouse_condition": get_warehouse_condition(filters.warehouse),
|
||||
"posting_date": filters.from_date,
|
||||
"posting_time": "00:00:00",
|
||||
"project": project,
|
||||
},
|
||||
for_report=True,
|
||||
)
|
||||
|
||||
opening_reco_vouchers = set(opening_reco_query.run(pluck=True))
|
||||
# check if any SLEs are actually Opening Stock Reconciliation
|
||||
for sle in list(sl_entries):
|
||||
if (
|
||||
sle.get("voucher_type") == "Stock Reconciliation"
|
||||
and sle.posting_date == filters.from_date
|
||||
and frappe.db.get_value("Stock Reconciliation", sle.voucher_no, "purpose") == "Opening Stock"
|
||||
):
|
||||
last_entry = sle
|
||||
sl_entries.remove(sle)
|
||||
|
||||
if opening_reco_vouchers:
|
||||
sl_entries[:] = [sle for sle in sl_entries if sle.get("voucher_no") not in opening_reco_vouchers]
|
||||
|
||||
sle_cond = (sle_doctype.posting_date < filters.from_date) | (
|
||||
(sle_doctype.posting_date == filters.from_date) & (sle_doctype.posting_time == "00:00:00")
|
||||
)
|
||||
if opening_reco_vouchers:
|
||||
sle_cond = sle_cond | (
|
||||
(sle_doctype.posting_date == filters.from_date)
|
||||
& (sle_doctype.voucher_no.isin(list(opening_reco_vouchers)))
|
||||
)
|
||||
|
||||
subq = (
|
||||
frappe.qb.from_(sle_doctype)
|
||||
.select(
|
||||
sle_doctype.qty_after_transaction,
|
||||
sle_doctype.stock_value,
|
||||
RowNumber()
|
||||
.over(sle_doctype.item_code, sle_doctype.warehouse)
|
||||
.orderby(sle_doctype.posting_datetime, sle_doctype.creation, sle_doctype.name, order=Order.desc)
|
||||
.as_("rn"),
|
||||
)
|
||||
.where(sle_doctype.docstatus < 2)
|
||||
.where(sle_doctype.is_cancelled == 0)
|
||||
.where(sle_doctype.item_code.isin(item_codes))
|
||||
.where(sle_doctype.warehouse.isin(warehouses))
|
||||
.where(sle_cond)
|
||||
)
|
||||
|
||||
for field in ["voucher_no", "project", "company"]:
|
||||
if filters.get(field):
|
||||
subq = subq.where(sle_doctype[field] == filters.get(field))
|
||||
|
||||
inventory_dimension_fields = get_inventory_dimension_fields()
|
||||
if inventory_dimension_fields:
|
||||
for fieldname in inventory_dimension_fields:
|
||||
if filters.get(fieldname):
|
||||
subq = subq.where(sle_doctype[fieldname].isin(filters.get(fieldname)))
|
||||
|
||||
query = (
|
||||
frappe.qb.from_(subq)
|
||||
.select(
|
||||
IfNull(Sum(subq.qty_after_transaction), 0.0).as_("total_qty"),
|
||||
IfNull(Sum(subq.stock_value), 0.0).as_("total_stock_value"),
|
||||
)
|
||||
.where(subq.rn == 1)
|
||||
)
|
||||
|
||||
res = query.run(as_dict=True)
|
||||
|
||||
total_qty = flt(res[0].total_qty) if res else 0.0
|
||||
total_stock_value = flt(res[0].total_stock_value) if res else 0.0
|
||||
valuation_rate = flt(total_stock_value / total_qty) if total_qty else 0.0
|
||||
|
||||
return {
|
||||
row = {
|
||||
"item_code": _("'Opening'"),
|
||||
"qty_after_transaction": total_qty,
|
||||
"valuation_rate": valuation_rate,
|
||||
"stock_value": total_stock_value,
|
||||
"qty_after_transaction": last_entry.get("qty_after_transaction", 0),
|
||||
"valuation_rate": last_entry.get("valuation_rate", 0),
|
||||
"stock_value": last_entry.get("stock_value", 0),
|
||||
}
|
||||
|
||||
|
||||
def get_matching_warehouses(warehouses):
|
||||
if not warehouses:
|
||||
return []
|
||||
|
||||
if isinstance(warehouses, str):
|
||||
warehouses = [warehouses]
|
||||
|
||||
warehouse_details = frappe.get_all(
|
||||
"Warehouse",
|
||||
filters={"name": ("in", warehouses)},
|
||||
fields=["lft", "rgt"],
|
||||
)
|
||||
|
||||
if not warehouse_details:
|
||||
return warehouses
|
||||
|
||||
wh = frappe.qb.DocType("Warehouse")
|
||||
cond = None
|
||||
for d in warehouse_details:
|
||||
c = (wh.lft >= d.lft) & (wh.rgt <= d.rgt)
|
||||
cond = c if cond is None else (cond | c)
|
||||
|
||||
matching = (frappe.qb.from_(wh).select(wh.name).where(cond)).run(pluck=True)
|
||||
|
||||
return matching if matching else warehouses
|
||||
return row
|
||||
|
||||
|
||||
def get_warehouse_condition(warehouses):
|
||||
@@ -865,15 +785,7 @@ def get_opening_balance_for_inv_dimension(filters, inv_dimension_wise_value):
|
||||
if not filters.item_code or not filters.warehouse or not filters.from_date:
|
||||
return
|
||||
|
||||
item_codes = filters.get("item_code")
|
||||
if isinstance(item_codes, str):
|
||||
item_codes = [item_codes]
|
||||
|
||||
warehouses = filters.get("warehouse")
|
||||
if isinstance(warehouses, str):
|
||||
warehouses = [warehouses]
|
||||
|
||||
if len(item_codes) > 1 or len(warehouses) > 1:
|
||||
if len(filters.get("item_code")) > 1 or len(filters.get("warehouse")) > 1:
|
||||
return
|
||||
|
||||
sl_doctype = frappe.qb.DocType("Stock Ledger Entry")
|
||||
@@ -893,11 +805,17 @@ def get_opening_balance_for_inv_dimension(filters, inv_dimension_wise_value):
|
||||
)
|
||||
)
|
||||
|
||||
if item_codes:
|
||||
query = query.where(sl_doctype.item_code.isin(item_codes))
|
||||
if filters.get("item_code"):
|
||||
if isinstance(filters.item_code, list | tuple):
|
||||
query = query.where(sl_doctype.item_code.isin(filters.item_code))
|
||||
else:
|
||||
query = query.where(sl_doctype.item_code == filters.item_code)
|
||||
|
||||
if warehouses:
|
||||
query = query.where(sl_doctype.warehouse.isin(warehouses))
|
||||
if filters.get("warehouse"):
|
||||
if isinstance(filters.warehouse, list | tuple):
|
||||
query = query.where(sl_doctype.warehouse.isin(filters.warehouse))
|
||||
else:
|
||||
query = query.where(sl_doctype.warehouse == filters.warehouse)
|
||||
|
||||
for key, value in inv_dimension_wise_value.items():
|
||||
if isinstance(value, list | tuple):
|
||||
|
||||
@@ -4,333 +4,18 @@
|
||||
import frappe
|
||||
from frappe.utils import add_days, today
|
||||
|
||||
from erpnext.stock.doctype.stock_entry.stock_entry_utils import make_stock_entry
|
||||
from erpnext.stock.report.stock_ledger.stock_ledger import execute
|
||||
from erpnext.maintenance.doctype.maintenance_schedule.test_maintenance_schedule import (
|
||||
make_serial_item_with_serial,
|
||||
)
|
||||
from erpnext.tests.utils import ERPNextTestSuite
|
||||
|
||||
WAREHOUSE = "Stores - _TC"
|
||||
|
||||
|
||||
class TestStockLedgerReport(ERPNextTestSuite):
|
||||
"""Correctness tests for the Stock Ledger report.
|
||||
|
||||
A shared `make_movements`/`run` pair keeps each test small without persisting
|
||||
any data: movements are created per test and rolled back, while the report runs
|
||||
read-only. Tests reuse bootstrap items and transact in `Stores - _TC`, which
|
||||
starts clean (zero balance) for these items.
|
||||
"""
|
||||
|
||||
def make_movements(self, item_code, movements):
|
||||
for movement in movements:
|
||||
make_stock_entry(item_code=item_code, **movement)
|
||||
|
||||
def run_report(self, item_code, from_date=None, to_date=None):
|
||||
filters = frappe._dict(
|
||||
class TestStockLedgerReeport(ERPNextTestSuite):
|
||||
def setUp(self) -> None:
|
||||
make_serial_item_with_serial(self, "_Test Stock Report Serial Item")
|
||||
self.filters = frappe._dict(
|
||||
company="_Test Company",
|
||||
from_date=from_date or add_days(today(), -1),
|
||||
to_date=to_date or today(),
|
||||
item_code=[item_code],
|
||||
warehouse=WAREHOUSE,
|
||||
)
|
||||
return list(execute(filters)[1])
|
||||
|
||||
def test_in_out_quantities_and_running_balance(self):
|
||||
item = "_Test Item"
|
||||
self.make_movements(
|
||||
item,
|
||||
[
|
||||
{"qty": 10, "to_warehouse": WAREHOUSE, "basic_rate": 100},
|
||||
{"qty": 4, "from_warehouse": WAREHOUSE},
|
||||
],
|
||||
)
|
||||
|
||||
rows = self.run_report(item)
|
||||
receipt = next(row for row in rows if row.get("in_qty"))
|
||||
issue = next(row for row in rows if row.get("out_qty"))
|
||||
|
||||
self.assertEqual(receipt["in_qty"], 10)
|
||||
self.assertEqual(receipt["qty_after_transaction"], 10)
|
||||
self.assertEqual(issue["out_qty"], -4)
|
||||
self.assertEqual(issue["qty_after_transaction"], 6)
|
||||
|
||||
def test_opening_balance_reflects_movements_before_from_date(self):
|
||||
item = "_Test Item"
|
||||
self.make_movements(
|
||||
item,
|
||||
[
|
||||
{
|
||||
"qty": 10,
|
||||
"to_warehouse": WAREHOUSE,
|
||||
"basic_rate": 100,
|
||||
"posting_date": add_days(today(), -10),
|
||||
},
|
||||
{"qty": 4, "from_warehouse": WAREHOUSE, "posting_date": today()},
|
||||
],
|
||||
)
|
||||
|
||||
rows = self.run_report(item, from_date=add_days(today(), -5), to_date=today())
|
||||
|
||||
# the receipt predates the range, so it surfaces as the opening balance
|
||||
self.assertEqual(rows[0]["item_code"], "'Opening'")
|
||||
self.assertEqual(rows[0]["qty_after_transaction"], 10)
|
||||
|
||||
# the in-range issue draws down from the opening balance
|
||||
issue = next(row for row in rows if row.get("out_qty"))
|
||||
self.assertEqual(issue["qty_after_transaction"], 6)
|
||||
|
||||
def test_filters_to_requested_item_only(self):
|
||||
item_a = "_Test Item"
|
||||
item_b = "_Test Item 2"
|
||||
self.make_movements(item_a, [{"qty": 5, "to_warehouse": WAREHOUSE, "basic_rate": 100}])
|
||||
self.make_movements(item_b, [{"qty": 7, "to_warehouse": WAREHOUSE, "basic_rate": 100}])
|
||||
|
||||
rows = self.run_report(item_a)
|
||||
item_codes = {row["item_code"] for row in rows if row.get("voucher_no")}
|
||||
self.assertEqual(item_codes, {item_a})
|
||||
|
||||
def test_multi_item_opening_balance_with_and_without_transactions(self):
|
||||
item_a = "_Test Item"
|
||||
item_b = "_Test Item 2"
|
||||
self.make_movements(
|
||||
item_a,
|
||||
[
|
||||
{
|
||||
"qty": 10,
|
||||
"to_warehouse": WAREHOUSE,
|
||||
"basic_rate": 100,
|
||||
"posting_date": add_days(today(), -10),
|
||||
}
|
||||
],
|
||||
)
|
||||
self.make_movements(
|
||||
item_b,
|
||||
[{"qty": 5, "to_warehouse": WAREHOUSE, "basic_rate": 50, "posting_date": add_days(today(), -10)}],
|
||||
)
|
||||
self.make_movements(
|
||||
item_a,
|
||||
[{"qty": 2, "from_warehouse": WAREHOUSE, "posting_date": today()}],
|
||||
)
|
||||
|
||||
filters = frappe._dict(
|
||||
company="_Test Company",
|
||||
from_date=add_days(today(), -5),
|
||||
to_date=today(),
|
||||
item_code=[item_a, item_b],
|
||||
warehouse=WAREHOUSE,
|
||||
)
|
||||
columns, rows = execute(filters)
|
||||
|
||||
opening_rows = [row for row in rows if row.get("item_code") == "'Opening'"]
|
||||
self.assertEqual(len(opening_rows), 1)
|
||||
self.assertEqual(opening_rows[0]["qty_after_transaction"], 15)
|
||||
|
||||
def test_multi_warehouse_opening_balance_aggregation(self):
|
||||
item = "_Test Item"
|
||||
warehouse_1 = "Stores - _TC"
|
||||
warehouse_2 = "Finished Goods - _TC"
|
||||
|
||||
self.make_movements(
|
||||
item,
|
||||
[
|
||||
{
|
||||
"qty": 10,
|
||||
"to_warehouse": warehouse_1,
|
||||
"basic_rate": 100,
|
||||
"posting_date": add_days(today(), -10),
|
||||
},
|
||||
{
|
||||
"qty": 20,
|
||||
"to_warehouse": warehouse_2,
|
||||
"basic_rate": 100,
|
||||
"posting_date": add_days(today(), -10),
|
||||
},
|
||||
],
|
||||
)
|
||||
|
||||
filters = frappe._dict(
|
||||
company="_Test Company",
|
||||
from_date=add_days(today(), -5),
|
||||
to_date=today(),
|
||||
item_code=[item],
|
||||
warehouse=[warehouse_1, warehouse_2],
|
||||
)
|
||||
columns, rows = execute(filters)
|
||||
|
||||
opening_rows = [row for row in rows if row.get("item_code") == "'Opening'"]
|
||||
self.assertEqual(len(opening_rows), 1)
|
||||
self.assertEqual(opening_rows[0]["qty_after_transaction"], 30)
|
||||
|
||||
def test_opening_stock_reconciliation_on_from_date_non_midnight_time(self):
|
||||
from erpnext.stock.doctype.stock_reconciliation.test_stock_reconciliation import (
|
||||
create_stock_reconciliation,
|
||||
)
|
||||
|
||||
item = "_Test Item"
|
||||
from_date = today()
|
||||
|
||||
sr = create_stock_reconciliation(
|
||||
item_code=item,
|
||||
warehouse=WAREHOUSE,
|
||||
qty=25,
|
||||
rate=100,
|
||||
posting_date=from_date,
|
||||
posting_time="10:30:00",
|
||||
purpose="Opening Stock",
|
||||
do_not_submit=False,
|
||||
)
|
||||
|
||||
filters = frappe._dict(
|
||||
company="_Test Company",
|
||||
from_date=from_date,
|
||||
to_date=from_date,
|
||||
item_code=[item],
|
||||
warehouse=WAREHOUSE,
|
||||
)
|
||||
columns, rows = execute(filters)
|
||||
|
||||
opening_rows = [row for row in rows if row.get("item_code") == "'Opening'"]
|
||||
self.assertEqual(len(opening_rows), 1)
|
||||
self.assertEqual(opening_rows[0]["qty_after_transaction"], 25)
|
||||
|
||||
# Ensure the Opening Stock Reconciliation is not duplicated in detail transaction rows
|
||||
reco_rows = [row for row in rows if row.get("voucher_no") == sr.name]
|
||||
self.assertEqual(len(reco_rows), 0)
|
||||
|
||||
def test_backdated_sle_independent_maxima_handling(self):
|
||||
item = "_Test Item"
|
||||
# Entry 1: Later posting date (2026-07-20), created first
|
||||
self.make_movements(
|
||||
item,
|
||||
[
|
||||
{
|
||||
"qty": 10,
|
||||
"to_warehouse": WAREHOUSE,
|
||||
"basic_rate": 100,
|
||||
"posting_date": add_days(today(), -10),
|
||||
}
|
||||
],
|
||||
)
|
||||
# Entry 2: Backdated posting date (2026-07-15), created LATER
|
||||
self.make_movements(
|
||||
item,
|
||||
[
|
||||
{
|
||||
"qty": 5,
|
||||
"to_warehouse": WAREHOUSE,
|
||||
"basic_rate": 100,
|
||||
"posting_date": add_days(today(), -15),
|
||||
}
|
||||
],
|
||||
)
|
||||
|
||||
filters = frappe._dict(
|
||||
company="_Test Company",
|
||||
from_date=add_days(today(), -5),
|
||||
to_date=today(),
|
||||
item_code=[item],
|
||||
warehouse=WAREHOUSE,
|
||||
)
|
||||
columns, rows = execute(filters)
|
||||
|
||||
opening_rows = [row for row in rows if row.get("item_code") == "'Opening'"]
|
||||
self.assertEqual(len(opening_rows), 1)
|
||||
# Should correctly pick the latest posting date entry (15 Qty) despite backdated creation order
|
||||
self.assertEqual(opening_rows[0]["qty_after_transaction"], 15)
|
||||
|
||||
def test_filtered_opening_balance_does_not_pick_excluded_creation_entry(self):
|
||||
item = "_Test Item"
|
||||
posting_date = add_days(today(), -10)
|
||||
posting_time = "09:00:00"
|
||||
|
||||
included_entry = make_stock_entry(
|
||||
item_code=item,
|
||||
qty=10,
|
||||
to_warehouse=WAREHOUSE,
|
||||
basic_rate=100,
|
||||
posting_date=posting_date,
|
||||
posting_time=posting_time,
|
||||
)
|
||||
make_stock_entry(
|
||||
item_code=item,
|
||||
qty=50,
|
||||
to_warehouse=WAREHOUSE,
|
||||
basic_rate=100,
|
||||
posting_date=posting_date,
|
||||
posting_time=posting_time,
|
||||
)
|
||||
|
||||
filters = frappe._dict(
|
||||
company="_Test Company",
|
||||
from_date=add_days(today(), -5),
|
||||
to_date=today(),
|
||||
item_code=[item],
|
||||
warehouse=WAREHOUSE,
|
||||
voucher_no=included_entry.name,
|
||||
)
|
||||
columns, rows = execute(filters)
|
||||
|
||||
opening_rows = [row for row in rows if row.get("item_code") == "'Opening'"]
|
||||
self.assertEqual(len(opening_rows), 1)
|
||||
self.assertEqual(opening_rows[0]["qty_after_transaction"], 10)
|
||||
|
||||
def test_tied_creation_terminal_sle_is_not_summed_twice(self):
|
||||
item = "_Test Item"
|
||||
posting_date = add_days(today(), -10)
|
||||
posting_time = "09:00:00"
|
||||
|
||||
stock_entry_1 = make_stock_entry(
|
||||
item_code=item,
|
||||
qty=10,
|
||||
to_warehouse=WAREHOUSE,
|
||||
basic_rate=100,
|
||||
posting_date=posting_date,
|
||||
posting_time=posting_time,
|
||||
)
|
||||
stock_entry_2 = make_stock_entry(
|
||||
item_code=item,
|
||||
qty=5,
|
||||
to_warehouse=WAREHOUSE,
|
||||
basic_rate=100,
|
||||
posting_date=posting_date,
|
||||
posting_time=posting_time,
|
||||
)
|
||||
|
||||
sle_rows = frappe.get_all(
|
||||
"Stock Ledger Entry",
|
||||
filters={
|
||||
"voucher_type": "Stock Entry",
|
||||
"voucher_no": ("in", [stock_entry_1.name, stock_entry_2.name]),
|
||||
"item_code": item,
|
||||
"warehouse": WAREHOUSE,
|
||||
"is_cancelled": 0,
|
||||
},
|
||||
fields=["name", "qty_after_transaction"],
|
||||
order_by="name desc",
|
||||
)
|
||||
self.assertEqual(len(sle_rows), 2)
|
||||
|
||||
for sle in sle_rows:
|
||||
frappe.db.set_value(
|
||||
"Stock Ledger Entry",
|
||||
sle.name,
|
||||
"creation",
|
||||
"2026-01-01 00:00:00.000000",
|
||||
update_modified=False,
|
||||
)
|
||||
|
||||
filters = frappe._dict(
|
||||
company="_Test Company",
|
||||
from_date=add_days(today(), -5),
|
||||
to_date=today(),
|
||||
item_code=[item],
|
||||
warehouse=WAREHOUSE,
|
||||
)
|
||||
columns, rows = execute(filters)
|
||||
|
||||
opening_rows = [row for row in rows if row.get("item_code") == "'Opening'"]
|
||||
self.assertEqual(len(opening_rows), 1)
|
||||
self.assertEqual(opening_rows[0]["qty_after_transaction"], sle_rows[0].qty_after_transaction)
|
||||
self.assertNotEqual(
|
||||
opening_rows[0]["qty_after_transaction"],
|
||||
sum(sle.qty_after_transaction for sle in sle_rows),
|
||||
from_date=today(),
|
||||
to_date=add_days(today(), 30),
|
||||
item_code=["_Test Stock Report Serial Item"],
|
||||
)
|
||||
|
||||
@@ -820,14 +820,13 @@ class BatchNoValuation(DeprecatedBatchNoValuation):
|
||||
"Serial and Batch Bundle", self.sle.serial_and_batch_bundle, "total_amount"
|
||||
)
|
||||
else:
|
||||
entries = self.get_batch_stock_before_date()
|
||||
self.stock_value_change = 0.0
|
||||
self.batch_avg_rate = defaultdict(float)
|
||||
self.available_qty = defaultdict(float)
|
||||
self.stock_value_differece = defaultdict(float)
|
||||
|
||||
self.seed_from_stock_closing_balance()
|
||||
|
||||
for ledger in self.get_batch_stock_before_date():
|
||||
for ledger in entries:
|
||||
self.stock_value_differece[ledger.batch_no] += flt(ledger.incoming_rate)
|
||||
self.available_qty[ledger.batch_no] += flt(ledger.qty)
|
||||
|
||||
@@ -835,52 +834,6 @@ class BatchNoValuation(DeprecatedBatchNoValuation):
|
||||
self.calculate_avg_rate_for_non_batchwise_valuation()
|
||||
self.set_stock_value_difference()
|
||||
|
||||
def seed_from_stock_closing_balance(self):
|
||||
self.stock_closing_from_datetime = None
|
||||
closing_entry = self.get_closing_entry_for_seeding()
|
||||
if not closing_entry:
|
||||
return
|
||||
|
||||
from erpnext.stock.utils import get_combine_datetime
|
||||
|
||||
self.stock_closing_from_datetime = get_combine_datetime(
|
||||
add_days(closing_entry.to_date, 1), "00:00:00"
|
||||
)
|
||||
|
||||
for row in self.get_stock_closing_balance_entries(closing_entry.name):
|
||||
self.stock_value_differece[row.batch_no] += flt(row.stock_value_difference)
|
||||
self.available_qty[row.batch_no] += flt(row.actual_qty)
|
||||
|
||||
def get_closing_entry_for_seeding(self):
|
||||
from erpnext.stock.doctype.stock_closing_entry.stock_closing_entry import (
|
||||
get_closing_entry_for_closed_period,
|
||||
)
|
||||
|
||||
if not self.batchwise_valuation_batches or not self.sle.posting_date:
|
||||
return None
|
||||
|
||||
company = self.sle.company or frappe.get_cached_value("Warehouse", self.sle.warehouse, "company")
|
||||
closing_entry = get_closing_entry_for_closed_period(company)
|
||||
if not closing_entry or getdate(self.sle.posting_date) <= getdate(closing_entry.to_date):
|
||||
return None
|
||||
|
||||
return closing_entry
|
||||
|
||||
def get_stock_closing_balance_entries(self, closing_entry):
|
||||
table = frappe.qb.DocType("Stock Closing Balance")
|
||||
|
||||
return (
|
||||
frappe.qb.from_(table)
|
||||
.select(table.batch_no, table.actual_qty, table.stock_value_difference)
|
||||
.where(
|
||||
(table.stock_closing_entry == closing_entry)
|
||||
& (table.item_code == self.sle.item_code)
|
||||
& (table.warehouse == self.sle.warehouse)
|
||||
& table.batch_no.isin(self.batchwise_valuation_batches)
|
||||
& (table.inventory_dimension_key.isnull() | (table.inventory_dimension_key == ""))
|
||||
)
|
||||
).run(as_dict=True)
|
||||
|
||||
def get_batch_stock_before_date(self) -> list[dict]:
|
||||
# Get batch wise stock value difference from Serial and Batch Bundle considering time condition
|
||||
if not self.batchwise_valuation_batches:
|
||||
@@ -888,45 +841,14 @@ class BatchNoValuation(DeprecatedBatchNoValuation):
|
||||
|
||||
child = frappe.qb.DocType("Serial and Batch Entry")
|
||||
|
||||
sle_creation = self.sle.creation if self.sle.get("name") else None
|
||||
if not self.sle.get("name") and self.sle.get("serial_and_batch_bundle"):
|
||||
sle_creation = frappe.db.get_value(
|
||||
"Stock Ledger Entry",
|
||||
{"serial_and_batch_bundle": self.sle.serial_and_batch_bundle, "is_cancelled": 0},
|
||||
"creation",
|
||||
)
|
||||
|
||||
timestamp_condition = ""
|
||||
if self.sle.posting_datetime:
|
||||
timestamp_condition = child.posting_datetime < self.sle.posting_datetime
|
||||
|
||||
sle_table = frappe.qb.DocType("Stock Ledger Entry")
|
||||
if sle_creation:
|
||||
# bundle creation and SLE creation are different timelines (a
|
||||
# bundle can be created much before its SLE), so break the tie
|
||||
# using the creation of the bundle's own SLE
|
||||
tie_condition = ExistsCriterion(
|
||||
frappe.qb.from_(sle_table)
|
||||
.select(sle_table.name)
|
||||
.where(
|
||||
(sle_table.serial_and_batch_bundle == child.parent)
|
||||
& (sle_table.is_cancelled == 0)
|
||||
& (sle_table.creation < sle_creation)
|
||||
)
|
||||
if self.sle.creation:
|
||||
timestamp_condition |= (child.posting_datetime == self.sle.posting_datetime) & (
|
||||
child.creation < self.sle.creation
|
||||
)
|
||||
else:
|
||||
# the current entry is not yet in the ledger and will get the
|
||||
# latest creation, so the same-timestamp entries which are
|
||||
# already in the ledger precede it
|
||||
tie_condition = ExistsCriterion(
|
||||
frappe.qb.from_(sle_table)
|
||||
.select(sle_table.name)
|
||||
.where(
|
||||
(sle_table.serial_and_batch_bundle == child.parent) & (sle_table.is_cancelled == 0)
|
||||
)
|
||||
)
|
||||
|
||||
timestamp_condition |= (child.posting_datetime == self.sle.posting_datetime) & tie_condition
|
||||
|
||||
query = (
|
||||
frappe.qb.from_(child)
|
||||
@@ -956,9 +878,6 @@ class BatchNoValuation(DeprecatedBatchNoValuation):
|
||||
if timestamp_condition:
|
||||
query = query.where(timestamp_condition)
|
||||
|
||||
if self.stock_closing_from_datetime:
|
||||
query = query.where(child.posting_datetime >= self.stock_closing_from_datetime)
|
||||
|
||||
return query.run(as_dict=True)
|
||||
|
||||
def prepare_batches(self):
|
||||
@@ -971,11 +890,6 @@ class BatchNoValuation(DeprecatedBatchNoValuation):
|
||||
self.batchwise_valuation_batches = []
|
||||
self.non_batchwise_valuation_batches = []
|
||||
|
||||
if batchwise_batches := self.sle.get("batchwise_valuation_batches"):
|
||||
self.batchwise_valuation_batches = list(batchwise_batches)
|
||||
self.non_batchwise_valuation_batches = list(set(self.batches) - set(batchwise_batches))
|
||||
return
|
||||
|
||||
if get_valuation_method(
|
||||
self.sle.item_code, self.sle.company
|
||||
) == "Moving Average" and frappe.get_single_value("Stock Settings", "do_not_use_batchwise_valuation"):
|
||||
|
||||
@@ -56,32 +56,6 @@ class SerialNoExistsInFutureTransaction(frappe.ValidationError):
|
||||
pass
|
||||
|
||||
|
||||
def validate_stock_frozen_by_closing_entry(sl_entries):
|
||||
from erpnext.stock.doctype.stock_closing_entry.stock_closing_entry import (
|
||||
get_closing_entry_for_closed_period,
|
||||
)
|
||||
|
||||
company = sl_entries[0].get("company")
|
||||
if not company:
|
||||
company = frappe.get_cached_value("Warehouse", sl_entries[0].get("warehouse"), "company")
|
||||
|
||||
closing_entry = get_closing_entry_for_closed_period(company)
|
||||
if not closing_entry:
|
||||
return
|
||||
|
||||
for sle in sl_entries:
|
||||
if sle.get("posting_date") and getdate(sle.get("posting_date")) <= getdate(closing_entry.to_date):
|
||||
frappe.throw(
|
||||
_(
|
||||
"Stock transactions dated on or before {0} are frozen because the period is closed and the Stock Closing Entry {1} has been generated. To make changes, cancel the Period Closing Voucher first."
|
||||
).format(
|
||||
frappe.bold(format_date(closing_entry.to_date)),
|
||||
get_link_to_form("Stock Closing Entry", closing_entry.name),
|
||||
),
|
||||
title=_("Stock Frozen"),
|
||||
)
|
||||
|
||||
|
||||
def make_sl_entries(sl_entries, allow_negative_stock=False, via_landed_cost_voucher=False):
|
||||
"""Create SL entries from SL entry dicts
|
||||
|
||||
@@ -96,8 +70,6 @@ def make_sl_entries(sl_entries, allow_negative_stock=False, via_landed_cost_vouc
|
||||
from erpnext.controllers.stock_controller import future_sle_exists
|
||||
|
||||
if sl_entries:
|
||||
validate_stock_frozen_by_closing_entry(sl_entries)
|
||||
|
||||
cancelled = sl_entries[0].get("is_cancelled")
|
||||
if cancelled:
|
||||
validate_cancellation(sl_entries)
|
||||
|
||||
Reference in New Issue
Block a user