mirror of
https://github.com/frappe/erpnext.git
synced 2026-04-29 03:28:32 +00:00
Merge pull request #43891 from frappe/version-15-hotfix
chore: release v15
This commit is contained in:
@@ -58,7 +58,7 @@ frappe.ui.form.on("Accounting Dimension", {
|
||||
},
|
||||
|
||||
label: function (frm) {
|
||||
frm.set_value("fieldname", frappe.model.scrub(frm.doc.label));
|
||||
frm.set_value("fieldname", frm.doc.label.replace(/ /g, "_").replace(/-/g, "_").toLowerCase());
|
||||
},
|
||||
|
||||
document_type: function (frm) {
|
||||
|
||||
@@ -7,6 +7,7 @@ import json
|
||||
import frappe
|
||||
from frappe import _, scrub
|
||||
from frappe.custom.doctype.custom_field.custom_field import create_custom_field
|
||||
from frappe.database.schema import validate_column_name
|
||||
from frappe.model import core_doctypes_list
|
||||
from frappe.model.document import Document
|
||||
from frappe.utils import cstr
|
||||
@@ -60,6 +61,7 @@ class AccountingDimension(Document):
|
||||
if not self.is_new():
|
||||
self.validate_document_type_change()
|
||||
|
||||
validate_column_name(self.fieldname)
|
||||
self.validate_dimension_defaults()
|
||||
|
||||
def validate_document_type_change(self):
|
||||
|
||||
@@ -323,6 +323,7 @@ class PaymentReconciliation(Document):
|
||||
"posting_date": inv.posting_date,
|
||||
"currency": inv.currency,
|
||||
"cost_center": inv.cost_center,
|
||||
"remarks": inv.remarks,
|
||||
}
|
||||
)
|
||||
)
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
"amount",
|
||||
"difference_amount",
|
||||
"sec_break1",
|
||||
"remark",
|
||||
"remarks",
|
||||
"currency",
|
||||
"exchange_rate",
|
||||
"cost_center"
|
||||
@@ -74,12 +74,6 @@
|
||||
"fieldname": "sec_break1",
|
||||
"fieldtype": "Section Break"
|
||||
},
|
||||
{
|
||||
"fieldname": "remark",
|
||||
"fieldtype": "Small Text",
|
||||
"label": "Remark",
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "currency",
|
||||
"fieldtype": "Link",
|
||||
@@ -105,12 +99,18 @@
|
||||
"fieldtype": "Link",
|
||||
"label": "Cost Center",
|
||||
"options": "Cost Center"
|
||||
},
|
||||
{
|
||||
"fieldname": "remarks",
|
||||
"fieldtype": "Small Text",
|
||||
"label": "Remarks",
|
||||
"read_only": 1
|
||||
}
|
||||
],
|
||||
"is_virtual": 1,
|
||||
"istable": 1,
|
||||
"links": [],
|
||||
"modified": "2023-11-17 17:33:34.818530",
|
||||
"modified": "2024-10-29 16:24:43.021230",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Payment Reconciliation Payment",
|
||||
|
||||
@@ -27,7 +27,7 @@ class PaymentReconciliationPayment(Document):
|
||||
reference_name: DF.DynamicLink | None
|
||||
reference_row: DF.Data | None
|
||||
reference_type: DF.Link | None
|
||||
remark: DF.SmallText | None
|
||||
remarks: DF.SmallText | None
|
||||
# end: auto-generated types
|
||||
|
||||
@staticmethod
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
"party_details",
|
||||
"party_type",
|
||||
"party",
|
||||
"party_name",
|
||||
"column_break_4",
|
||||
"reference_doctype",
|
||||
"reference_name",
|
||||
@@ -422,13 +423,19 @@
|
||||
"label": "Party Account Currency",
|
||||
"options": "Currency",
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "party_name",
|
||||
"fieldtype": "Data",
|
||||
"label": "Party Name",
|
||||
"read_only": 1
|
||||
}
|
||||
],
|
||||
"in_create": 1,
|
||||
"index_web_pages_for_search": 1,
|
||||
"is_submittable": 1,
|
||||
"links": [],
|
||||
"modified": "2024-09-16 17:50:54.440090",
|
||||
"modified": "2024-10-23 12:23:40.117336",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Payment Request",
|
||||
@@ -467,4 +474,4 @@
|
||||
"sort_field": "modified",
|
||||
"sort_order": "DESC",
|
||||
"states": []
|
||||
}
|
||||
}
|
||||
@@ -71,6 +71,7 @@ class PaymentRequest(Document):
|
||||
outstanding_amount: DF.Currency
|
||||
party: DF.DynamicLink | None
|
||||
party_account_currency: DF.Link | None
|
||||
party_name: DF.Data | None
|
||||
party_type: DF.Link | None
|
||||
payment_account: DF.ReadOnly | None
|
||||
payment_channel: DF.Literal["", "Email", "Phone", "Other"]
|
||||
@@ -303,12 +304,12 @@ class PaymentRequest(Document):
|
||||
return controller.get_payment_url(
|
||||
**{
|
||||
"amount": flt(self.grand_total, self.precision("grand_total")),
|
||||
"title": data.company.encode("utf-8"),
|
||||
"description": self.subject.encode("utf-8"),
|
||||
"title": data.company,
|
||||
"description": self.subject,
|
||||
"reference_doctype": "Payment Request",
|
||||
"reference_docname": self.name,
|
||||
"payer_email": self.email_to or frappe.session.user,
|
||||
"payer_name": frappe.safe_encode(data.customer_name),
|
||||
"payer_name": data.customer_name,
|
||||
"order_id": self.name,
|
||||
"currency": self.currency,
|
||||
}
|
||||
@@ -609,6 +610,7 @@ def make_payment_request(**args):
|
||||
"party_type": party_type,
|
||||
"party": args.get("party") or ref_doc.get("customer"),
|
||||
"bank_account": bank_account,
|
||||
"party_name": args.get("party_name") or ref_doc.get("customer_name"),
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
@@ -413,11 +413,16 @@ class PeriodClosingVoucher(AccountsController):
|
||||
return closing_entries
|
||||
|
||||
def is_first_period_closing_voucher(self):
|
||||
return not frappe.db.exists(
|
||||
first_pcv = frappe.db.get_value(
|
||||
"Period Closing Voucher",
|
||||
{"company": self.company, "docstatus": 1, "name": ("!=", self.name)},
|
||||
{"company": self.company, "docstatus": 1},
|
||||
"name",
|
||||
order_by="period_end_date",
|
||||
)
|
||||
|
||||
if not first_pcv or first_pcv == self.name:
|
||||
return True
|
||||
|
||||
def cancel_gl_entries(self):
|
||||
if self.get_gle_count_against_current_pcv() > 5000:
|
||||
frappe.enqueue(
|
||||
|
||||
@@ -31,6 +31,13 @@ erpnext.accounts.PurchaseInvoice = class PurchaseInvoice extends erpnext.buying.
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
this.frm.set_query("expense_account", "items", function () {
|
||||
return {
|
||||
query: "erpnext.controllers.queries.get_expense_account",
|
||||
filters: { company: doc.company },
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
onload() {
|
||||
@@ -335,7 +342,9 @@ erpnext.accounts.PurchaseInvoice = class PurchaseInvoice extends erpnext.buying.
|
||||
party_type: "Supplier",
|
||||
account: this.frm.doc.credit_to,
|
||||
price_list: this.frm.doc.buying_price_list,
|
||||
fetch_payment_terms_template: cint(!this.frm.doc.ignore_default_payment_terms_template),
|
||||
fetch_payment_terms_template: cint(
|
||||
(this.frm.doc.is_return == 0) & !this.frm.doc.ignore_default_payment_terms_template
|
||||
),
|
||||
},
|
||||
function () {
|
||||
me.apply_pricing_rule();
|
||||
@@ -506,13 +515,6 @@ cur_frm.fields_dict["select_print_heading"].get_query = function (doc, cdt, cdn)
|
||||
};
|
||||
};
|
||||
|
||||
cur_frm.set_query("expense_account", "items", function (doc) {
|
||||
return {
|
||||
query: "erpnext.controllers.queries.get_expense_account",
|
||||
filters: { company: doc.company },
|
||||
};
|
||||
});
|
||||
|
||||
cur_frm.set_query("wip_composite_asset", "items", function () {
|
||||
return {
|
||||
filters: { is_composite_asset: 1, docstatus: 0 },
|
||||
|
||||
@@ -1134,12 +1134,14 @@
|
||||
"label": "Payment Terms"
|
||||
},
|
||||
{
|
||||
"depends_on": "eval:(!doc.is_paid && !doc.is_return)",
|
||||
"fieldname": "payment_terms_template",
|
||||
"fieldtype": "Link",
|
||||
"label": "Payment Terms Template",
|
||||
"options": "Payment Terms Template"
|
||||
},
|
||||
{
|
||||
"depends_on": "eval:(!doc.is_paid && !doc.is_return)",
|
||||
"fieldname": "payment_schedule",
|
||||
"fieldtype": "Table",
|
||||
"label": "Payment Schedule",
|
||||
@@ -1631,7 +1633,7 @@
|
||||
"idx": 204,
|
||||
"is_submittable": 1,
|
||||
"links": [],
|
||||
"modified": "2024-09-11 12:59:19.130593",
|
||||
"modified": "2024-10-25 18:13:01.944477",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Purchase Invoice",
|
||||
|
||||
@@ -1593,7 +1593,11 @@ class PurchaseInvoice(BuyingController):
|
||||
for proj, value in projects.items():
|
||||
res = frappe.qb.from_(pj).select(pj.total_purchase_cost).where(pj.name == proj).for_update().run()
|
||||
current_purchase_cost = res and res[0][0] or 0
|
||||
frappe.db.set_value("Project", proj, "total_purchase_cost", current_purchase_cost + value)
|
||||
# frappe.db.set_value("Project", proj, "total_purchase_cost", current_purchase_cost + value)
|
||||
project_doc = frappe.get_doc("Project", proj)
|
||||
project_doc.total_purchase_cost = current_purchase_cost + value
|
||||
project_doc.calculate_gross_margin()
|
||||
project_doc.db_update()
|
||||
|
||||
def validate_supplier_invoice(self):
|
||||
if self.bill_date:
|
||||
|
||||
@@ -505,7 +505,8 @@
|
||||
"fieldtype": "Link",
|
||||
"label": "Project",
|
||||
"options": "Project",
|
||||
"print_hide": 1
|
||||
"print_hide": 1,
|
||||
"search_index": 1
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 1,
|
||||
@@ -974,7 +975,7 @@
|
||||
"idx": 1,
|
||||
"istable": 1,
|
||||
"links": [],
|
||||
"modified": "2024-07-19 12:12:42.449298",
|
||||
"modified": "2024-10-28 15:06:19.246141",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Purchase Invoice Item",
|
||||
|
||||
@@ -339,6 +339,9 @@ erpnext.accounts.SalesInvoiceController = class SalesInvoiceController extends (
|
||||
account: this.frm.doc.debit_to,
|
||||
price_list: this.frm.doc.selling_price_list,
|
||||
pos_profile: pos_profile,
|
||||
fetch_payment_terms_template: cint(
|
||||
(this.frm.doc.is_return == 0) & !this.frm.doc.ignore_default_payment_terms_template
|
||||
),
|
||||
},
|
||||
function () {
|
||||
me.apply_pricing_rule();
|
||||
|
||||
@@ -1734,9 +1734,11 @@ class SalesInvoice(SellingController):
|
||||
)
|
||||
|
||||
def update_project(self):
|
||||
if self.project:
|
||||
project = frappe.get_doc("Project", self.project)
|
||||
unique_projects = list(set([d.project for d in self.get("items") if d.project]))
|
||||
for p in unique_projects:
|
||||
project = frappe.get_doc("Project", p)
|
||||
project.update_billed_amount()
|
||||
project.calculate_gross_margin()
|
||||
project.db_update()
|
||||
|
||||
def verify_payment_amount_is_positive(self):
|
||||
|
||||
@@ -812,7 +812,8 @@
|
||||
"fieldname": "project",
|
||||
"fieldtype": "Link",
|
||||
"label": "Project",
|
||||
"options": "Project"
|
||||
"options": "Project",
|
||||
"search_index": 1
|
||||
},
|
||||
{
|
||||
"depends_on": "eval:parent.update_stock == 1",
|
||||
@@ -927,7 +928,7 @@
|
||||
"idx": 1,
|
||||
"istable": 1,
|
||||
"links": [],
|
||||
"modified": "2024-05-23 16:36:18.970862",
|
||||
"modified": "2024-10-28 15:06:40.980995",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Sales Invoice Item",
|
||||
|
||||
@@ -514,7 +514,7 @@ def get_tds_amount(ldc, parties, inv, tax_details, vouchers):
|
||||
payment_entry_filters.pop("apply_tax_withholding_amount", None)
|
||||
payment_entry_filters.pop("tax_withholding_category", None)
|
||||
|
||||
supp_credit_amt = frappe.db.get_value("Purchase Invoice", invoice_filters, field) or 0.0
|
||||
supp_inv_credit_amt = frappe.db.get_value("Purchase Invoice", invoice_filters, field) or 0.0
|
||||
|
||||
supp_jv_credit_amt = (
|
||||
frappe.db.get_value(
|
||||
@@ -538,7 +538,7 @@ def get_tds_amount(ldc, parties, inv, tax_details, vouchers):
|
||||
group_by="payment_type",
|
||||
)
|
||||
|
||||
supp_credit_amt += supp_jv_credit_amt
|
||||
supp_credit_amt = supp_jv_credit_amt
|
||||
supp_credit_amt += inv.tax_withholding_net_total
|
||||
|
||||
for type in payment_entry_amounts:
|
||||
@@ -556,18 +556,18 @@ def get_tds_amount(ldc, parties, inv, tax_details, vouchers):
|
||||
tax_withholding_net_total = inv.tax_withholding_net_total
|
||||
|
||||
if (threshold and tax_withholding_net_total >= threshold) or (
|
||||
cumulative_threshold and supp_credit_amt >= cumulative_threshold
|
||||
cumulative_threshold and (supp_credit_amt + supp_inv_credit_amt) >= cumulative_threshold
|
||||
):
|
||||
# Get net total again as TDS is calculated on net total
|
||||
# Grand is used to just check for threshold breach
|
||||
net_total = (
|
||||
frappe.db.get_value("Purchase Invoice", invoice_filters, "sum(tax_withholding_net_total)") or 0.0
|
||||
)
|
||||
supp_credit_amt += net_total
|
||||
|
||||
if (cumulative_threshold and supp_credit_amt >= cumulative_threshold) and cint(
|
||||
tax_details.tax_on_excess_amount
|
||||
):
|
||||
# Get net total again as TDS is calculated on net total
|
||||
# Grand is used to just check for threshold breach
|
||||
net_total = (
|
||||
frappe.db.get_value("Purchase Invoice", invoice_filters, "sum(tax_withholding_net_total)")
|
||||
or 0.0
|
||||
)
|
||||
net_total += inv.tax_withholding_net_total
|
||||
supp_credit_amt = net_total - cumulative_threshold
|
||||
|
||||
if ldc and is_valid_certificate(ldc, inv.get("posting_date") or inv.get("transaction_date"), 0):
|
||||
|
||||
@@ -121,6 +121,46 @@ class TestTaxWithholdingCategory(FrappeTestCase):
|
||||
for d in reversed(invoices):
|
||||
d.cancel()
|
||||
|
||||
def test_cumulative_threshold_with_party_ledger_amount_on_net_total(self):
|
||||
invoices = []
|
||||
frappe.db.set_value(
|
||||
"Supplier", "Test TDS Supplier3", "tax_withholding_category", "Advance TDS Category"
|
||||
)
|
||||
|
||||
# Invoice with tax and without exceeding single and cumulative thresholds
|
||||
for _ in range(2):
|
||||
pi = create_purchase_invoice(supplier="Test TDS Supplier3", rate=1000, do_not_save=True)
|
||||
pi.apply_tds = 1
|
||||
pi.append(
|
||||
"taxes",
|
||||
{
|
||||
"category": "Total",
|
||||
"charge_type": "Actual",
|
||||
"account_head": "_Test Account VAT - _TC",
|
||||
"cost_center": "Main - _TC",
|
||||
"tax_amount": 500,
|
||||
"description": "Test",
|
||||
"add_deduct_tax": "Add",
|
||||
},
|
||||
)
|
||||
pi.save()
|
||||
pi.submit()
|
||||
invoices.append(pi)
|
||||
|
||||
# Third Invoice exceeds single threshold and not exceeding cumulative threshold
|
||||
pi1 = create_purchase_invoice(supplier="Test TDS Supplier3", rate=6000)
|
||||
pi1.apply_tds = 1
|
||||
pi1.save()
|
||||
pi1.submit()
|
||||
invoices.append(pi1)
|
||||
|
||||
# Cumulative threshold is 10,000
|
||||
# Threshold calculation should be only on the third invoice
|
||||
self.assertEqual(pi1.taxes[0].tax_amount, 800)
|
||||
|
||||
for d in reversed(invoices):
|
||||
d.cancel()
|
||||
|
||||
def test_cumulative_threshold_tcs(self):
|
||||
frappe.db.set_value(
|
||||
"Customer", "Test TCS Customer", "tax_withholding_category", "Cumulative Threshold TCS"
|
||||
|
||||
@@ -522,7 +522,8 @@ class ReceivablePayableReport:
|
||||
from `tab{row.voucher_type}` si, `tabPayment Schedule` ps
|
||||
where
|
||||
si.name = ps.parent and
|
||||
si.name = %s
|
||||
si.name = %s and
|
||||
si.is_return = 0
|
||||
order by ps.paid_amount desc, due_date
|
||||
""",
|
||||
row.voucher_no,
|
||||
|
||||
@@ -348,10 +348,18 @@ def get_accounts_with_children(accounts):
|
||||
return frappe.qb.from_(doctype).select(doctype.name).where(Criterion.any(conditions)).run(pluck=True)
|
||||
|
||||
|
||||
def set_bill_no(gl_entries):
|
||||
inv_details = get_supplier_invoice_details()
|
||||
for gl in gl_entries:
|
||||
gl["bill_no"] = inv_details.get(gl.get("against_voucher"), "")
|
||||
|
||||
|
||||
def get_data_with_opening_closing(filters, account_details, accounting_dimensions, gl_entries):
|
||||
data = []
|
||||
totals_dict = get_totals_dict()
|
||||
|
||||
set_bill_no(gl_entries)
|
||||
|
||||
gle_map = initialize_gle_map(gl_entries, filters, totals_dict)
|
||||
|
||||
totals, entries = get_accountwise_gle(filters, accounting_dimensions, gl_entries, gle_map, totals_dict)
|
||||
@@ -539,7 +547,6 @@ def get_account_type_map(company):
|
||||
|
||||
def get_result_as_list(data, filters):
|
||||
balance, _balance_in_account_currency = 0, 0
|
||||
inv_details = get_supplier_invoice_details()
|
||||
|
||||
for d in data:
|
||||
if not d.get("posting_date"):
|
||||
@@ -549,7 +556,6 @@ def get_result_as_list(data, filters):
|
||||
d["balance"] = balance
|
||||
|
||||
d["account_currency"] = filters.account_currency
|
||||
d["bill_no"] = inv_details.get(d.get("against_voucher"), "")
|
||||
|
||||
return data
|
||||
|
||||
|
||||
@@ -130,6 +130,7 @@ class PaymentLedger:
|
||||
)
|
||||
|
||||
def get_columns(self):
|
||||
company_currency = frappe.get_cached_value("Company", self.filters.get("company"), "default_currency")
|
||||
options = None
|
||||
self.columns.append(
|
||||
dict(
|
||||
@@ -194,7 +195,7 @@ class PaymentLedger:
|
||||
label=_("Amount"),
|
||||
fieldname="amount",
|
||||
fieldtype="Currency",
|
||||
options="Company:company:default_currency",
|
||||
options=company_currency,
|
||||
width="100",
|
||||
)
|
||||
)
|
||||
|
||||
@@ -526,7 +526,8 @@ def get_invoice_tax_map(invoice_list, invoice_income_map, income_accounts, inclu
|
||||
tax_details = frappe.db.sql(
|
||||
"""select parent, account_head,
|
||||
sum(base_tax_amount_after_discount_amount) as tax_amount
|
||||
from `tabSales Taxes and Charges` where parent in (%s) group by parent, account_head"""
|
||||
from `tabSales Taxes and Charges` where parent in (%s) and parenttype = 'Sales Invoice'
|
||||
group by parent, account_head"""
|
||||
% ", ".join(["%s"] * len(invoice_list)),
|
||||
tuple(inv.name for inv in invoice_list),
|
||||
as_dict=1,
|
||||
|
||||
@@ -1969,6 +1969,7 @@ class QueryPaymentLedger:
|
||||
ple.cost_center.as_("cost_center"),
|
||||
Sum(ple.amount).as_("amount"),
|
||||
Sum(ple.amount_in_account_currency).as_("amount_in_account_currency"),
|
||||
ple.remarks,
|
||||
)
|
||||
.where(ple.delinked == 0)
|
||||
.where(Criterion.all(filter_on_voucher_no))
|
||||
@@ -2031,6 +2032,7 @@ class QueryPaymentLedger:
|
||||
Table("vouchers").due_date,
|
||||
Table("vouchers").currency,
|
||||
Table("vouchers").cost_center.as_("cost_center"),
|
||||
Table("vouchers").remarks,
|
||||
)
|
||||
.where(Criterion.all(filter_on_outstanding_amount))
|
||||
)
|
||||
|
||||
@@ -790,14 +790,19 @@ class Asset(AccountsController):
|
||||
args.get("value_after_depreciation")
|
||||
)
|
||||
else:
|
||||
value = flt(args.get("expected_value_after_useful_life")) / flt(self.gross_purchase_amount)
|
||||
value = flt(args.get("expected_value_after_useful_life")) / (
|
||||
flt(self.gross_purchase_amount) - flt(self.opening_accumulated_depreciation)
|
||||
)
|
||||
|
||||
depreciation_rate = math.pow(
|
||||
value,
|
||||
1.0
|
||||
/ (
|
||||
(
|
||||
flt(args.get("total_number_of_depreciations"), 2)
|
||||
(
|
||||
flt(args.get("total_number_of_depreciations"), 2)
|
||||
- flt(self.opening_number_of_booked_depreciations)
|
||||
)
|
||||
* flt(args.get("frequency_of_depreciation"))
|
||||
)
|
||||
/ 12
|
||||
|
||||
@@ -146,8 +146,8 @@ frappe.ui.form.on("Request for Quotation", {
|
||||
return;
|
||||
}
|
||||
},
|
||||
"Download PDF for Supplier",
|
||||
"Download"
|
||||
__("Download PDF for Supplier"),
|
||||
__("Download")
|
||||
);
|
||||
},
|
||||
__("Tools")
|
||||
@@ -272,9 +272,10 @@ frappe.ui.form.on("Request for Quotation", {
|
||||
});
|
||||
};
|
||||
|
||||
dialog.fields_dict.note.$wrapper
|
||||
.append(`<p class="small text-muted">This is a preview of the email to be sent. A PDF of the document will
|
||||
automatically be attached with the email.</p>`);
|
||||
const msg = __(
|
||||
"This is a preview of the email to be sent. A PDF of the document will automatically be attached with the email."
|
||||
);
|
||||
dialog.fields_dict.note.$wrapper.append(`<p class="small text-muted">${msg}</p>`);
|
||||
|
||||
dialog.show();
|
||||
},
|
||||
|
||||
@@ -451,6 +451,11 @@ class AccountsController(TransactionBase):
|
||||
)
|
||||
|
||||
def validate_invoice_documents_schedule(self):
|
||||
if self.is_return:
|
||||
self.payment_terms_template = ""
|
||||
self.payment_schedule = []
|
||||
return
|
||||
|
||||
self.validate_payment_schedule_dates()
|
||||
self.set_due_date()
|
||||
self.set_payment_schedule()
|
||||
@@ -465,7 +470,7 @@ class AccountsController(TransactionBase):
|
||||
self.validate_payment_schedule_amount()
|
||||
|
||||
def validate_all_documents_schedule(self):
|
||||
if self.doctype in ("Sales Invoice", "Purchase Invoice") and not self.is_return:
|
||||
if self.doctype in ("Sales Invoice", "Purchase Invoice"):
|
||||
self.validate_invoice_documents_schedule()
|
||||
elif self.doctype in ("Quotation", "Purchase Order", "Sales Order"):
|
||||
self.validate_non_invoice_documents_schedule()
|
||||
|
||||
@@ -79,6 +79,9 @@ def validate_returned_items(doc):
|
||||
if doc.doctype in ["Purchase Invoice", "Purchase Receipt", "Subcontracting Receipt"]:
|
||||
select_fields += ",rejected_qty, received_qty"
|
||||
|
||||
if doc.doctype in ["Purchase Receipt", "Purchase Invoice"]:
|
||||
select_fields += ",name"
|
||||
|
||||
for d in frappe.db.sql(
|
||||
f"""select {select_fields} from `tab{doc.doctype} Item` where parent = %s""",
|
||||
doc.return_against,
|
||||
@@ -104,15 +107,24 @@ def validate_returned_items(doc):
|
||||
|
||||
items_returned = False
|
||||
for d in doc.get("items"):
|
||||
key = d.item_code
|
||||
raise_exception = False
|
||||
if doc.doctype in ["Purchase Receipt", "Purchase Invoice"]:
|
||||
field = frappe.scrub(doc.doctype) + "_item"
|
||||
if d.get(field):
|
||||
key = (d.item_code, d.get(field))
|
||||
raise_exception = True
|
||||
|
||||
if d.item_code and (flt(d.qty) < 0 or flt(d.get("received_qty")) < 0):
|
||||
if d.item_code not in valid_items:
|
||||
frappe.throw(
|
||||
if key not in valid_items:
|
||||
frappe.msgprint(
|
||||
_("Row # {0}: Returned Item {1} does not exist in {2} {3}").format(
|
||||
d.idx, d.item_code, doc.doctype, doc.return_against
|
||||
)
|
||||
),
|
||||
raise_exception=raise_exception,
|
||||
)
|
||||
else:
|
||||
ref = valid_items.get(d.item_code, frappe._dict())
|
||||
ref = valid_items.get(key, frappe._dict())
|
||||
validate_quantity(doc, d, ref, valid_items, already_returned_items)
|
||||
|
||||
if (
|
||||
@@ -193,8 +205,12 @@ def validate_quantity(doc, args, ref, valid_items, already_returned_items):
|
||||
def get_ref_item_dict(valid_items, ref_item_row):
|
||||
from erpnext.stock.doctype.serial_no.serial_no import get_serial_nos
|
||||
|
||||
key = ref_item_row.item_code
|
||||
if ref_item_row.get("name"):
|
||||
key = (ref_item_row.item_code, ref_item_row.name)
|
||||
|
||||
valid_items.setdefault(
|
||||
ref_item_row.item_code,
|
||||
key,
|
||||
frappe._dict(
|
||||
{
|
||||
"qty": 0,
|
||||
@@ -208,7 +224,7 @@ def get_ref_item_dict(valid_items, ref_item_row):
|
||||
}
|
||||
),
|
||||
)
|
||||
item_dict = valid_items[ref_item_row.item_code]
|
||||
item_dict = valid_items[key]
|
||||
item_dict["qty"] += ref_item_row.qty
|
||||
item_dict["stock_qty"] += ref_item_row.get("stock_qty", 0)
|
||||
if ref_item_row.get("rate", 0) > item_dict["rate"]:
|
||||
|
||||
@@ -561,11 +561,11 @@ class SubcontractingController(StockController):
|
||||
use_serial_batch_fields = frappe.db.get_single_value("Stock Settings", "use_serial_batch_fields")
|
||||
|
||||
if self.doctype == self.subcontract_data.order_doctype:
|
||||
rm_obj.required_qty = qty
|
||||
rm_obj.amount = rm_obj.required_qty * rm_obj.rate
|
||||
rm_obj.required_qty = flt(qty, rm_obj.precision("required_qty"))
|
||||
rm_obj.amount = flt(rm_obj.required_qty * rm_obj.rate, rm_obj.precision("amount"))
|
||||
else:
|
||||
rm_obj.consumed_qty = qty
|
||||
rm_obj.required_qty = bom_item.required_qty or qty
|
||||
rm_obj.consumed_qty = flt(qty, rm_obj.precision("consumed_qty"))
|
||||
rm_obj.required_qty = flt(bom_item.required_qty or qty, rm_obj.precision("required_qty"))
|
||||
rm_obj.serial_and_batch_bundle = None
|
||||
setattr(
|
||||
rm_obj, self.subcontract_data.order_field, item_row.get(self.subcontract_data.order_field)
|
||||
@@ -664,8 +664,8 @@ class SubcontractingController(StockController):
|
||||
self.__set_serial_nos(item_row, rm_obj)
|
||||
|
||||
def __set_consumed_qty(self, rm_obj, consumed_qty, required_qty=0):
|
||||
rm_obj.required_qty = required_qty
|
||||
rm_obj.consumed_qty = consumed_qty
|
||||
rm_obj.required_qty = flt(required_qty, rm_obj.precision("required_qty"))
|
||||
rm_obj.consumed_qty = flt(consumed_qty, rm_obj.precision("consumed_qty"))
|
||||
|
||||
def __set_serial_nos(self, item_row, rm_obj):
|
||||
key = (rm_obj.rm_item_code, item_row.item_code, item_row.get(self.subcontract_data.order_field))
|
||||
|
||||
@@ -1234,6 +1234,7 @@ def make_subcontracted_items():
|
||||
"Subcontracted Item SA6": {},
|
||||
"Subcontracted Item SA7": {},
|
||||
"Subcontracted Item SA8": {},
|
||||
"Subcontracted Item SA9": {"stock_uom": "Litre"},
|
||||
}
|
||||
|
||||
for item, properties in sub_contracted_items.items():
|
||||
@@ -1254,6 +1255,7 @@ def make_raw_materials():
|
||||
"Subcontracted SRM Item 4": {"has_serial_no": 1, "serial_no_series": "SRII.####"},
|
||||
"Subcontracted SRM Item 5": {"has_serial_no": 1, "serial_no_series": "SRIID.####"},
|
||||
"Subcontracted SRM Item 8": {},
|
||||
"Subcontracted SRM Item 9": {"stock_uom": "Litre"},
|
||||
}
|
||||
|
||||
for item, properties in raw_materials.items():
|
||||
@@ -1280,6 +1282,7 @@ def make_service_items():
|
||||
"Subcontracted Service Item 6": {},
|
||||
"Subcontracted Service Item 7": {},
|
||||
"Subcontracted Service Item 8": {},
|
||||
"Subcontracted Service Item 9": {},
|
||||
}
|
||||
|
||||
for item, properties in service_items.items():
|
||||
|
||||
@@ -127,8 +127,8 @@ erpnext.LeadController = class LeadController extends frappe.ui.form.Controller
|
||||
fieldname: "prospect_name",
|
||||
fieldtype: "Data",
|
||||
default: frm.doc.company_name,
|
||||
reqd: 1,
|
||||
depends_on: "create_prospect",
|
||||
mandatory_depends_on: "create_prospect",
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@@ -941,26 +941,19 @@ class JobCard(Document):
|
||||
|
||||
qty = 0
|
||||
if self.work_order:
|
||||
doc = frappe.get_doc("Work Order", self.work_order)
|
||||
if doc.transfer_material_against == "Job Card" and not doc.skip_transfer:
|
||||
completed = True
|
||||
min_qty = []
|
||||
for d in doc.operations:
|
||||
if d.status != "Completed":
|
||||
completed = False
|
||||
if d.completed_qty:
|
||||
min_qty.append(d.completed_qty)
|
||||
else:
|
||||
min_qty = []
|
||||
break
|
||||
|
||||
if completed:
|
||||
job_cards = frappe.get_all(
|
||||
"Job Card",
|
||||
filters={"work_order": self.work_order, "docstatus": ("!=", 2)},
|
||||
fields="sum(transferred_qty) as qty",
|
||||
group_by="operation_id",
|
||||
)
|
||||
if min_qty:
|
||||
qty = min(min_qty)
|
||||
|
||||
if job_cards:
|
||||
qty = min(d.qty for d in job_cards)
|
||||
|
||||
doc.db_set("material_transferred_for_manufacturing", qty)
|
||||
doc.db_set("material_transferred_for_manufacturing", qty)
|
||||
|
||||
self.set_status(update_status)
|
||||
|
||||
|
||||
@@ -45,6 +45,7 @@ frappe.ui.form.on("Project", {
|
||||
frm.set_query("sales_order", function () {
|
||||
var filters = {
|
||||
project: ["in", frm.doc.__islocal ? [""] : [frm.doc.name, ""]],
|
||||
company: frm.doc.company,
|
||||
};
|
||||
|
||||
if (frm.doc.customer) {
|
||||
|
||||
@@ -93,14 +93,14 @@ class Project(Document):
|
||||
|
||||
def validate(self):
|
||||
if not self.is_new():
|
||||
self.copy_from_template()
|
||||
self.copy_from_template() # nosemgrep
|
||||
self.send_welcome_email()
|
||||
self.update_costing()
|
||||
self.update_percent_complete()
|
||||
self.validate_from_to_dates("expected_start_date", "expected_end_date")
|
||||
self.validate_from_to_dates("actual_start_date", "actual_end_date")
|
||||
|
||||
def copy_from_template(self):
|
||||
def copy_from_template(self): # nosemgrep
|
||||
"""
|
||||
Copy tasks from template
|
||||
"""
|
||||
@@ -205,7 +205,7 @@ class Project(Document):
|
||||
self.db_update()
|
||||
|
||||
def after_insert(self):
|
||||
self.copy_from_template()
|
||||
self.copy_from_template() # nosemgrep
|
||||
if self.sales_order:
|
||||
frappe.db.set_value("Sales Order", self.sales_order, "project", self.name)
|
||||
|
||||
@@ -324,9 +324,13 @@ class Project(Document):
|
||||
self.total_sales_amount = total_sales_amount and total_sales_amount[0][0] or 0
|
||||
|
||||
def update_billed_amount(self):
|
||||
# nosemgrep
|
||||
total_billed_amount = frappe.db.sql(
|
||||
"""select sum(base_net_total)
|
||||
from `tabSales Invoice` where project = %s and docstatus=1""",
|
||||
"""select sum(base_net_amount)
|
||||
from `tabSales Invoice Item` si_item, `tabSales Invoice` si
|
||||
where si_item.parent = si.name
|
||||
and if(si_item.project, si_item.project, si.project) = %s
|
||||
and si.docstatus=1""",
|
||||
self.name,
|
||||
)
|
||||
|
||||
@@ -676,31 +680,8 @@ def update_project_sales_billing():
|
||||
return
|
||||
|
||||
# Else simply fallback to Daily
|
||||
exists_query = "(SELECT 1 from `tab{doctype}` where docstatus = 1 and project = `tabProject`.name)"
|
||||
project_map = {}
|
||||
for project_details in frappe.db.sql(
|
||||
"""
|
||||
SELECT name, 1 as order_exists, null as invoice_exists from `tabProject` where
|
||||
exists {order_exists}
|
||||
union
|
||||
SELECT name, null as order_exists, 1 as invoice_exists from `tabProject` where
|
||||
exists {invoice_exists}
|
||||
""".format(
|
||||
order_exists=exists_query.format(doctype="Sales Order"),
|
||||
invoice_exists=exists_query.format(doctype="Sales Invoice"),
|
||||
),
|
||||
as_dict=True,
|
||||
):
|
||||
project = project_map.setdefault(
|
||||
project_details.name, frappe.get_doc("Project", project_details.name)
|
||||
)
|
||||
if project_details.order_exists:
|
||||
project.update_sales_amount()
|
||||
if project_details.invoice_exists:
|
||||
project.update_billed_amount()
|
||||
|
||||
for project in project_map.values():
|
||||
project.save()
|
||||
for project in frappe.get_all("Project", filters={"status": ["!=", "Cancelled"]}):
|
||||
frappe.get_doc("Project", project.name).save()
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
@@ -751,7 +732,6 @@ def get_users_email(doc):
|
||||
def calculate_total_purchase_cost(project: str | None = None):
|
||||
if project:
|
||||
pitem = qb.DocType("Purchase Invoice Item")
|
||||
frappe.qb.DocType("Purchase Invoice Item")
|
||||
total_purchase_cost = (
|
||||
qb.from_(pitem)
|
||||
.select(Sum(pitem.base_net_amount))
|
||||
|
||||
@@ -22,6 +22,46 @@ class OverWorkLoggedError(frappe.ValidationError):
|
||||
|
||||
|
||||
class Timesheet(Document):
|
||||
# begin: auto-generated types
|
||||
# This code is auto-generated. Do not modify anything in this block.
|
||||
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from frappe.types import DF
|
||||
|
||||
from erpnext.projects.doctype.timesheet_detail.timesheet_detail import TimesheetDetail
|
||||
|
||||
amended_from: DF.Link | None
|
||||
base_total_billable_amount: DF.Currency
|
||||
base_total_billed_amount: DF.Currency
|
||||
base_total_costing_amount: DF.Currency
|
||||
company: DF.Link | None
|
||||
currency: DF.Link | None
|
||||
customer: DF.Link | None
|
||||
department: DF.Link | None
|
||||
employee: DF.Link | None
|
||||
employee_name: DF.Data | None
|
||||
end_date: DF.Date | None
|
||||
exchange_rate: DF.Float
|
||||
naming_series: DF.Literal["TS-.YYYY.-"]
|
||||
note: DF.TextEditor | None
|
||||
parent_project: DF.Link | None
|
||||
per_billed: DF.Percent
|
||||
sales_invoice: DF.Link | None
|
||||
start_date: DF.Date | None
|
||||
status: DF.Literal["Draft", "Submitted", "Billed", "Payslip", "Completed", "Cancelled"]
|
||||
time_logs: DF.Table[TimesheetDetail]
|
||||
title: DF.Data | None
|
||||
total_billable_amount: DF.Currency
|
||||
total_billable_hours: DF.Float
|
||||
total_billed_amount: DF.Currency
|
||||
total_billed_hours: DF.Float
|
||||
total_costing_amount: DF.Currency
|
||||
total_hours: DF.Float
|
||||
user: DF.Link | None
|
||||
# end: auto-generated types
|
||||
|
||||
def validate(self):
|
||||
self.set_status()
|
||||
self.validate_dates()
|
||||
|
||||
@@ -15,6 +15,7 @@ def execute(filters=None):
|
||||
filters=filters,
|
||||
fields=[
|
||||
"name",
|
||||
"project_name",
|
||||
"status",
|
||||
"percent_complete",
|
||||
"expected_start_date",
|
||||
@@ -48,6 +49,11 @@ def get_columns():
|
||||
"options": "Project",
|
||||
"width": 200,
|
||||
},
|
||||
{
|
||||
"fieldname": "project_name",
|
||||
"label": _("Project Name"),
|
||||
"width": 200,
|
||||
},
|
||||
{
|
||||
"fieldname": "project_type",
|
||||
"label": _("Type"),
|
||||
@@ -82,7 +88,7 @@ def get_chart_data(data):
|
||||
overdue = []
|
||||
|
||||
for project in data:
|
||||
labels.append(project.name)
|
||||
labels.append(project.project_name)
|
||||
total.append(project.total_tasks)
|
||||
completed.append(project.completed_tasks)
|
||||
overdue.append(project.overdue_tasks)
|
||||
|
||||
@@ -375,7 +375,8 @@ erpnext.TransactionController = class TransactionController extends erpnext.taxe
|
||||
recipient_id: me.frm.doc.contact_email,
|
||||
payment_request_type: payment_request_type,
|
||||
party_type: payment_request_type == 'Outward' ? "Supplier" : "Customer",
|
||||
party: payment_request_type == 'Outward' ? me.frm.doc.supplier : me.frm.doc.customer
|
||||
party: payment_request_type == 'Outward' ? me.frm.doc.supplier : me.frm.doc.customer,
|
||||
party_name:payment_request_type == 'Outward' ? me.frm.doc.supplier_name : me.frm.doc.customer_name
|
||||
},
|
||||
callback: function(r) {
|
||||
if(!r.exc){
|
||||
@@ -2438,7 +2439,7 @@ erpnext.TransactionController = class TransactionController extends erpnext.taxe
|
||||
payment_terms_template() {
|
||||
var me = this;
|
||||
const doc = this.frm.doc;
|
||||
if(doc.payment_terms_template && doc.doctype !== 'Delivery Note') {
|
||||
if(doc.payment_terms_template && doc.doctype !== 'Delivery Note' && doc.is_return == 0) {
|
||||
var posting_date = doc.posting_date || doc.transaction_date;
|
||||
frappe.call({
|
||||
method: "erpnext.controllers.accounts_controller.get_payment_terms",
|
||||
|
||||
@@ -29,6 +29,7 @@ erpnext.sales_common = {
|
||||
query: "erpnext.controllers.queries.get_project_name",
|
||||
filters: {
|
||||
customer: doc.customer,
|
||||
company: doc.company,
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
@@ -547,6 +547,8 @@ erpnext.PointOfSale.Controller = class {
|
||||
|
||||
async on_cart_update(args) {
|
||||
frappe.dom.freeze();
|
||||
if (this.frm.doc.set_warehouse != this.settings.warehouse)
|
||||
this.frm.doc.set_warehouse = this.settings.warehouse;
|
||||
let item_row = undefined;
|
||||
try {
|
||||
let { field, value, item } = args;
|
||||
|
||||
@@ -350,6 +350,11 @@ erpnext.PointOfSale.Payment = class {
|
||||
}
|
||||
|
||||
checkout() {
|
||||
const frm = this.events.get_frm();
|
||||
frm.cscript.calculate_outstanding_amount();
|
||||
frm.refresh_field("outstanding_amount");
|
||||
frm.refresh_field("paid_amount");
|
||||
frm.refresh_field("base_paid_amount");
|
||||
this.events.toggle_other_sections(true);
|
||||
this.toggle_component(true);
|
||||
|
||||
|
||||
@@ -1020,7 +1020,6 @@ def make_sales_invoice(source_name, target_doc=None, args=None):
|
||||
"parent": "delivery_note",
|
||||
"so_detail": "so_detail",
|
||||
"against_sales_order": "sales_order",
|
||||
"serial_no": "serial_no",
|
||||
"cost_center": "cost_center",
|
||||
},
|
||||
"postprocess": update_item,
|
||||
|
||||
@@ -830,6 +830,15 @@ frappe.ui.form.on("Stock Entry", {
|
||||
});
|
||||
|
||||
frappe.ui.form.on("Stock Entry Detail", {
|
||||
set_basic_rate_manually(frm, cdt, cdn) {
|
||||
let row = locals[cdt][cdn];
|
||||
frm.fields_dict.items.grid.update_docfield_property(
|
||||
"basic_rate",
|
||||
"read_only",
|
||||
row?.set_basic_rate_manually ? 0 : 1
|
||||
);
|
||||
},
|
||||
|
||||
qty(frm, cdt, cdn) {
|
||||
frm.events.set_basic_rate(frm, cdt, cdn);
|
||||
},
|
||||
|
||||
@@ -25,6 +25,7 @@ from erpnext.controllers.tests.test_subcontracting_controller import (
|
||||
make_subcontracted_items,
|
||||
set_backflush_based_on,
|
||||
)
|
||||
from erpnext.manufacturing.doctype.production_plan.test_production_plan import make_bom
|
||||
from erpnext.stock.doctype.item.test_item import make_item
|
||||
from erpnext.stock.doctype.stock_entry.test_stock_entry import make_stock_entry
|
||||
from erpnext.subcontracting.doctype.subcontracting_order.subcontracting_order import (
|
||||
@@ -683,6 +684,28 @@ class TestSubcontractingOrder(FrappeTestCase):
|
||||
|
||||
self.assertEqual(requested_qty, new_requested_qty)
|
||||
|
||||
def test_subcontracting_order_rm_required_items_for_precision(self):
|
||||
item_code = "Subcontracted Item SA9"
|
||||
raw_materials = ["Subcontracted SRM Item 9"]
|
||||
if not frappe.db.exists("BOM", {"item": item_code}):
|
||||
make_bom(item=item_code, raw_materials=raw_materials, rate=100, rm_qty=1.04)
|
||||
|
||||
service_items = [
|
||||
{
|
||||
"warehouse": "_Test Warehouse - _TC",
|
||||
"item_code": "Subcontracted Service Item 9",
|
||||
"qty": 1, # 202.0656,
|
||||
"rate": 100,
|
||||
"fg_item": "Subcontracted Item SA9",
|
||||
"fg_item_qty": 202.0656,
|
||||
},
|
||||
]
|
||||
|
||||
sco = get_subcontracting_order(service_items=service_items)
|
||||
sco.reload()
|
||||
|
||||
self.assertEqual(sco.supplied_items[0].required_qty, 210.149)
|
||||
|
||||
|
||||
def create_subcontracting_order(**args):
|
||||
args = frappe._dict(args)
|
||||
|
||||
@@ -331,9 +331,12 @@ class SubcontractingReceipt(SubcontractingController):
|
||||
supplied_items_details[item.name] = {}
|
||||
|
||||
for supplied_item in supplied_items:
|
||||
if supplied_item.rm_item_code not in supplied_items_details[item.name]:
|
||||
supplied_items_details[item.name][supplied_item.rm_item_code] = 0.0
|
||||
|
||||
supplied_items_details[item.name][
|
||||
supplied_item.rm_item_code
|
||||
] = supplied_item.available_qty
|
||||
] += supplied_item.available_qty
|
||||
else:
|
||||
for item in self.get("supplied_items"):
|
||||
item.available_qty_for_consumption = supplied_items_details.get(item.reference_name, {}).get(
|
||||
|
||||
@@ -173,11 +173,11 @@
|
||||
<div class="col-xs-8 col-sm-10">
|
||||
{{ d.item_code }}
|
||||
<div class="text-muted small item-description">
|
||||
{{ html2text(d.description) | truncate(140) }}
|
||||
{{ html2text(d.description or "") | truncate(140) }}
|
||||
</div>
|
||||
<span class="text-muted mt-2 d-l-n order-qty">
|
||||
{{ _("Qty ") }}({{ d.get_formatted("qty") }})
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
{% endmacro %}
|
||||
{% endmacro %}
|
||||
|
||||
@@ -11929,3 +11929,185 @@ Website Theme,Webseiten-Thema,
|
||||
Workflow Action,Workflow-Aktion,
|
||||
Workflow State,Workflow-Status,
|
||||
{0} is not running. Cannot trigger events for this Document,{0} läuft nicht. Ereignisse für dieses Dokument können nicht ausgelöst werden,
|
||||
"""SN-01::10"" for ""SN-01"" to ""SN-10""","""SN-01::10"" für ""SN-01"" bis ""SN-10""",
|
||||
"<span class=""h4""><b>Masters & Reports</b></span>","<span class=""h4""><b>Stammdaten & Berichte</b></span>",
|
||||
"<span class=""h4""><b>Quick Access</b></span>","<span class=""h4""><b>Schnellzugriff</b></span>",
|
||||
"<span class=""h4""><b>Reports & Masters</b></span>","<span class=""h4""><b>Berichte & Stammdaten</b></span>",
|
||||
"<span class=""h4""><b>Reports & Masters</b></span>","<span class=""h4""><b>Berichte & Stammdaten</b></span>",
|
||||
"<span class=""h4""><b>Settings</b></span>","<span class=""h4""><b>Einstellungen</b></span>",
|
||||
"<span class=""h4""><b>Shortcuts</b></span>","<span class=""h4""><b>Verknüpfungen</b></span>",
|
||||
"<span class=""h4""><b>Your Shortcuts
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</b></span>","<span class=""h4""><b>Ihre Verknüpfungen
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</b></span>",
|
||||
"<span class=""h4""><b>Your Shortcuts</b></span>","<span class=""h4""><b>Ihre Verknüpfungen</b></span>",
|
||||
<strong>Grand Total:</strong> {0},<strong>Gesamtsumme:</strong>{0},
|
||||
<strong>Outstanding Amount:</strong> {0},<strong>Ausstehender Betrag:</strong> {0},
|
||||
Against Customer Order {0},Gegen Kundenauftrag {0},
|
||||
Against Supplier Invoice {0},Gegen Lieferantenrechnung {0},
|
||||
Ageing Range,Alterungsbereich,
|
||||
Allocate Payment Request,Zahlungsanfrage zuweisen,
|
||||
Amount in party's bank account currency,Betrag in der Währung des Bankkontos des Beteiligten,
|
||||
Amount in transaction currency,Betrag in Transaktionswährung,
|
||||
BIN Qty,BIN Menge,
|
||||
BOM and Production,Stückliste und Produktion,
|
||||
Balance Stock Value,Bestandswert,
|
||||
Base Cost Per Unit,Grundkosten pro Einheit,
|
||||
Base Rate,Basispreis,
|
||||
Base Tax Withholding Net Total,Basis-Steuereinbehalt-Nettosumme,
|
||||
Base Total,Basis-Summe,
|
||||
Base Total Billable Amount,Basis Gesamter abrechenbarer Betrag,
|
||||
Batch Expiry Date,Ablaufdatum der Charge,
|
||||
Bill for Rejected Quantity in Purchase Invoice,Rechnung für abgelehnte Menge in der Eingangsrechnung,
|
||||
Calculate daily depreciation using total days in depreciation period,Tägliche Abschreibung anhand der Gesamttage im Abschreibungszeitraum berechnen,
|
||||
Call Schedule Row {0}: To time slot should always be ahead of From time slot.,Anrufplanzeile {0}: Das Zeitfenster Bis sollte immer vor dem Zeitfenster Von liegen.,
|
||||
Cannot find a default warehouse for item {0}. Please set one in the Item Master or in Stock Settings.,Es wurde kein Standardlager für den Artikel {0} gefunden. Bitte legen Sie eines im Artikelstamm oder in den Lagereinstellungen fest.,
|
||||
Cannot {0} from {2} without any negative outstanding invoice,Kann nicht {0} von {2} ohne negative ausstehende Rechnung,
|
||||
Cheques and Deposits Incorrectly cleared,Falsch verrechnete Schecks und Einzahlungen,
|
||||
Columns are not according to template. Please compare the uploaded file with standard template,Die Spalten stimmen nicht mit der Vorlage überein. Bitte vergleichen Sie die hochgeladene Datei mit der Standardvorlage,
|
||||
Company is mandatory,Unternehmen ist obligatorisch,
|
||||
Completion Date can not be before Failure Date. Please adjust the dates accordingly.,Das Fertigstellungsdatum kann nicht vor dem Ausfalldatum liegen. Bitte passen Sie die Daten entsprechend an.,
|
||||
Consumed Stock Items or Consumed Asset Items are mandatory for creating new composite asset,Verbrauchte Lagerartikel oder verbrauchte Vermögensgegenstand-Artikel sind für die Erstellung obligatorisch,
|
||||
Convert to Item Based Reposting,Umstellung auf artikelbasiertes Umbuchen,
|
||||
Create Workstation,Arbeitsplatz erstellen,
|
||||
Creating Journal Entries...,Journaleinträge erstellen...,
|
||||
Creating Purchase Invoices ...,Eingangsrechnungen erstellen ...,
|
||||
Creating Sales Invoices ...,Ausgangsrechnungen erstellen ...,
|
||||
Currency Exchange Settings Result,Währungsumtauscheinstellungen Ergebnis,
|
||||
Deal Owner,Besitzer des Deals,
|
||||
Decapitalized,Dekapitalisiert,
|
||||
Dependant SLE Voucher Detail No,Unterhaltsberechtigter SLE Beleg Detail Nr.,
|
||||
Disassemble,Demontage,
|
||||
Documents: {0} have deferred revenue/expense enabled for them. Cannot repost.,Dokumente: {0} hat vertagte Einnahmen/Ausgaben aktiviert. Kann nicht erneut posten.,
|
||||
Don't Reserve Sales Order Qty on Sales Return,Menge des Auftrags nicht bei der Rücksendung reservieren,
|
||||
Enter Manually,Manuell eingeben,
|
||||
Failed to post depreciation entries,Abschreibungsbuchungen fehlgeschlagen,
|
||||
Filters missing,Filter fehlen,
|
||||
"For Return Invoices with Stock effect, '0' qty Items are not allowed. Following rows are affected: {0}",Bei Retourenrechnungen mit Lagereffekt sind Artikel mit einer Menge von '0' nicht zulässig. Folgende Zeilen sind betroffen: {0},
|
||||
"For the item {0}, the quantity should be {1} according to the BOM {2}.",Für den Artikel {0} sollte die Menge gemäß Stückliste {2} {1} betragen.,
|
||||
"For the {0}, no stock is available for the return in the warehouse {1}.",Für {0} ist im Lager {1} kein Bestand für die Retoure verfügbar.,
|
||||
Force-Fetch Subscription Updates,Abonnement-Updates erzwingen,
|
||||
From Date is mandatory,Von-Datum ist obligatorisch,
|
||||
From Prospect,Von Interessenten,
|
||||
Gross Purchase Amount Too Low: {0} cannot be depreciated over {1} cycles with a frequency of {2} depreciations.,Bruttokaufbetrag zu niedrig: {0} kann nicht über {1} Zyklen mit einer Häufigkeit von {2} Abschreibungen abgeschrieben werden.,
|
||||
If enabled then system won't apply the pricing rule on the delivery note which will be create from the pick list,"Falls aktiviert, wird das System die Preisregel nicht auf den Lieferschein anwenden, der aus der Pickliste erstellt wird",
|
||||
Impairment,Wertminderung,
|
||||
Include Closed Orders,Geschlossene Aufträge/Bestellungen einbeziehen,
|
||||
Invalid Allocated Amount,Ungültiger zugewiesener Betrag,
|
||||
Invalid Amount,Ungültiger Betrag,
|
||||
Is Standard,Ist Standard,
|
||||
Item {0} does not exist.,Artikel {0} existiert nicht.,
|
||||
Items {0} do not exist in the Item master.,Artikel {0} sind nicht im Artikelstamm vorhanden.,
|
||||
Journal entries have been created,Journaleinträge wurden erstellt,
|
||||
Net total calculation precision loss,Präzisionsverlust bei Berechnung der Nettosumme,
|
||||
Only Deduct Tax On Excess Amount ,Nur den überschüssigen Betrag versteuern ,
|
||||
Payment Ledger Entry,Zahlungsbucheintrag,
|
||||
Payment Requests cannot be created against: {0},Zahlungsanforderungen können nicht erstellt werden für: {0},
|
||||
Period Closing Entry For Current Period,Periodenabschlussbuchung für aktuelle Periode,
|
||||
Provisional Account,Vorläufiges Konto,
|
||||
Rate of Stock UOM,Einzelpreis der Lager-ME,
|
||||
Raw Materials Consumption ,Rohstoffverbrauch ,
|
||||
Recalculating Purchase Cost against this Project...,Neuberechnung der Anschaffungskosten für dieses Projekt...,
|
||||
Reference DocType,Referenz DocType,
|
||||
Round Tax Amount Row-wise,Steuerbetrag zeilenweise runden,
|
||||
Rounding gain/loss Entry for Stock Transfer,Rundungsgewinn/-verlustbuchung für Umlagerung,
|
||||
Row #{0}: Only {1} available to reserve for the Item {2},Zeile #{0}: Nur {1} zur Reservierung für den Artikel {2} verfügbar,
|
||||
Row #{}: The original Invoice {} of return invoice {} is not consolidated.,Zeile #{}: Die ursprüngliche Rechnung {} der Rechnungskorrektur {} ist nicht konsolidiert.,
|
||||
Row {0}: Item {1} must be a subcontracted item.,Zeile {0}: Artikel {1} muss ein an Dritte vergebener Artikel sein.,
|
||||
Row {0}: Please provide a valid Delivery Note Item or Packed Item reference.,Zeile {0}: Bitte geben Sie einen gültigen Lieferschein Artikel oder verpackten Artikel an.,
|
||||
Row {0}: Target Warehouse is mandatory for internal transfers,Zeile {0}: Ziellager ist für interne Transfers obligatorisch,
|
||||
Row({0}): Outstanding Amount cannot be greater than actual Outstanding Amount {1} in {2},Zeile({0}): Ausstehender Betrag kann nicht größer sein als der tatsächliche ausstehende Betrag {1} in {2},
|
||||
Rows with Same Account heads will be merged on Ledger,Zeilen mit denselben Konten werden im Hauptbuch zusammengefasst,
|
||||
Select Warehouses to get Stock for Materials Planning,"Wählen Sie Lager aus, um Bestände für die Materialplanung zu erhalten",
|
||||
Select an invoice to load summary data,"Wählen Sie eine Rechnung aus, um die Zusammenfassung zu laden",
|
||||
Serial / Batch Bundle,Serien- / Chargenbündel,
|
||||
Serial / Batch Bundle Missing,Serien- / Chargenbündel fehlt,
|
||||
Serial No Range,Seriennummernbereich,
|
||||
Serial and Batch Details,Serien- und Chargendetails,
|
||||
Sets 'Accepted Warehouse' in each row of the Items table.,Legt in jeder Zeile der Artikeltabelle das Annahmelager fest.,
|
||||
Sets 'Rejected Warehouse' in each row of the Items table.,Legt in jeder Zeile der Artikeltabelle das „Ausschusslager“ fest.,
|
||||
Shelf Life in Days,Haltbarkeitsdauer in Tagen,
|
||||
Show Disabled Warehouses,Deaktivierte Lager anzeigen,
|
||||
Show GL Balance,Hauptbuchsaldo anzeigen,
|
||||
Show Pay Button in Purchase Order Portal,Schaltfläche „Bezahlen“ im Bestellportal anzeigen,
|
||||
Show Taxes as Table in Print,Steuern als Tabelle im Druck anzeigen,
|
||||
Show net values in opening and closing columns,Nettowerte in Eröffnungs- und Abschlussspalten anzeigen,
|
||||
Show with upcoming revenue/expense,Mit kommenden Einnahmen/Ausgaben anzeigen,
|
||||
Something went wrong please try again,"Etwas ist schief gelaufen, bitte versuchen Sie es erneut",
|
||||
South Africa VAT Account,Südafrika Mehrwertsteuer-Konto,
|
||||
South Africa VAT Settings,Südafrika Mehrwertsteuer-Einstellungen,
|
||||
Start Date should be lower than End Date,Das Startdatum muss vor dem Enddatum liegen,
|
||||
Start Deletion,Löschen starten,
|
||||
Start Time can't be greater than or equal to End Time for {0}.,Die Startzeit kann nicht größer oder gleich der Endzeit für {0} sein.,
|
||||
Started a background job to create {1} {0},Hintergrundjob zum Erstellen von {1} {0} gestartet,
|
||||
Status set to rejected as there are one or more rejected readings.,"Der Status wurde auf abgelehnt gesetzt, da es einen oder mehrere abgelehnte Messwerte gibt.",
|
||||
Stock Consumed During Repair,Während der Reparatur verbrauchter Bestand,
|
||||
Stock Consumption Details,Details zum Lagerverbrauch,
|
||||
Stock Planning,Bestandsplanung,
|
||||
Stock Reservation,Bestandsreservierung,
|
||||
Stock Reservation Entries Cancelled,Bestandsreservierungen storniert,
|
||||
Stock Reservation Entries Created,Bestandsreservierungen erstellt,
|
||||
Stock Reservation Entry,Bestandsreservierungseintrag,
|
||||
Stock Reservation Entry cannot be updated as it has been delivered.,"Der Bestandsreservierungseintrag kann nicht aktualisiert werden, da er bereits geliefert wurde.",
|
||||
"Stock Reservation Entry created against a Pick List cannot be updated. If you need to make changes, we recommend canceling the existing entry and creating a new one.","Ein anhand einer Kommissionierliste erstellter Bestandsreservierungseintrag kann nicht aktualisiert werden. Wenn Sie Änderungen vornehmen müssen, empfehlen wir, den vorhandenen Eintrag zu stornieren und einen neuen zu erstellen.",
|
||||
Stock Reservation can only be created against {0}.,Bestandsreservierungen können nur gegen {0} erstellt werden.,
|
||||
Stock Reserved Qty (in Stock UOM),Reservierter Bestand (in Lager-ME),
|
||||
Stock Unreservation,Aufhebung der Bestandsreservierung,
|
||||
Stock/Accounts can not be frozen as processing of backdated entries is going on. Please try again later.,"Lagerbestände/Konten können nicht eingefroren werden, da die Verarbeitung rückwirkender Einträge noch läuft. Bitte versuchen Sie es später erneut.",
|
||||
Supplied Item,Gelieferter Artikel,
|
||||
Supplies subject to the reverse charge provision,"Lieferungen, die der Reverse-Charge-Regelung unterliegen",
|
||||
Task {0} depends on Task {1}. Please add Task {1} to the Tasks list.,Aufgabe {0} hängt von Aufgabe {1} ab. Bitte fügen Sie Aufgabe {1} zur Aufgabenliste hinzu.,
|
||||
Tax Amount will be rounded on a row(items) level,Der Steuerbetrag wird auf (Artikel-)Zeilenebene gerundet,
|
||||
Tax Refunds provided to Tourists under the Tax Refunds for Tourists Scheme,Steuererstattungen für Touristen im Rahmen der Steuererstattungsregelung für Touristen,
|
||||
"Tax detail table fetched from item master as a string and stored in this field.
|
||||
Used for Taxes and Charges","Steuerdetailtabelle, die aus dem Artikelstamm als Zeichenfolge abgerufen und in diesem Feld gespeichert wird.
|
||||
Wird für Steuern und Gebühren verwendet",
|
||||
"The Payment Request {0} is already paid, cannot process payment twice","Die Auszahlungsanforderung {0} ist bereits bezahlt, die Zahlung kann nicht zweimal verarbeitet werden",
|
||||
The Serial No at Row #{0}: {1} is not available in warehouse {2}.,Die Seriennummer in Zeile #{0}: {1} ist im Lager {2} nicht verfügbar.,
|
||||
The Work Order is mandatory for Disassembly Order,Der Arbeitsauftrag ist obligatorisch für den Demontageauftrag,
|
||||
The allocated amount is greater than the outstanding amount of Payment Request {0},Der zugewiesene Betrag ist größer als der ausstehende Betrag der Zahlungsanforderung {0},
|
||||
The field {0} in row {1} is not set,Das Feld {0} in der Zeile {1} ist nicht gesetzt,
|
||||
The following invalid Pricing Rules are deleted:,Die folgenden ungültigen Preisregeln werden gelöscht:,
|
||||
The original invoice should be consolidated before or along with the return invoice.,Die Originalrechnung sollte vor oder zusammen mit der Erstattungsrechnung konsolidiert werden.,
|
||||
"The sync has started in the background, please check the {0} list for new records.",Die Synchronisierung wurde im Hintergrund gestartet. Bitte überprüfen Sie die Liste {0} auf neue Datensätze.,
|
||||
"The users with this Role are allowed to create/modify a stock transaction, even though the transaction is frozen.","Die Benutzer mit dieser Rolle dürfen eine Lagerbewegungen erstellen/ändern, auch wenn die Transaktion eingefroren ist.",
|
||||
There are no active Fiscal Years for which Demo Data can be generated.,"Es gibt keine aktiven Geschäftsjahre, für die Demodaten erstellt werden können.",
|
||||
There were issues unlinking payment entry {0}.,Es gab Probleme bei der Aufhebung der Verknüpfung der Zahlung {0}.,
|
||||
"This is enabled by default. If you want to plan materials for sub-assemblies of the Item you're manufacturing leave this enabled. If you plan and manufacture the sub-assemblies separately, you can disable this checkbox.","Diese Option ist standardmäßig aktiviert. Wenn Sie Materialien für Unterbaugruppen des Artikels, den Sie herstellen, planen möchten, lassen Sie diese Option aktiviert. Wenn Sie die Unterbaugruppen separat planen und herstellen, können Sie dieses Kontrollkästchen deaktivieren.",
|
||||
To Date is mandatory,Bis Datum ist obligatorisch,
|
||||
To Delivery Date,Bis Liefertermin,
|
||||
To Due Date,Bis Fälligkeitsdatum,
|
||||
To Reference Date,Bis Stichtag,
|
||||
To cancel a {} you need to cancel the POS Closing Entry {}.,"Um einen {} zu stornieren, müssen Sie die POS-Abschlussbuchung {} stornieren.",
|
||||
Total Incoming Value (Receipt),Gesamter eingehender Wert (Empfang),
|
||||
Total Number of Booked Depreciations ,Gesamtzahl der gebuchten Abschreibungen ,
|
||||
Total Operation Time,Gesamtbetriebszeit,
|
||||
Total Other Charges,Sonstige Kosten insgesamt,
|
||||
Total Purchase Amount,Gesamtkaufbetrag,
|
||||
Total Purchase Cost has been updated,Die Gesamteinkaufskosten wurden aktualisiert,
|
||||
UnReconcile,Zuordnung aufheben,
|
||||
Unrealized Profit / Loss account for intra-company transfers,Konto für nicht realisierte Gewinne/Verluste aus konzerninternen Transfers,
|
||||
Unrealized Profit/Loss account for intra-company transfers,Konto für nicht realisierte Gewinne/Verluste aus konzerninternen Transfers,
|
||||
Validate Components Quantities Per BOM,Anzahl der Komponenten pro Stückliste überprüfen,
|
||||
Validate Pricing Rule,Preisregel validieren,
|
||||
Validate Stock on Save,Lagerbestand beim Speichern validieren,
|
||||
Warning on Negative Stock,Warnung vor negativem Bestand,
|
||||
You cannot create a {0} within the closed Accounting Period {1},Sie können innerhalb der abgeschlossenen Abrechnungsperiode {1} kein(e) {0} erstellen,
|
||||
dated {0},von {0},
|
||||
must be between 0 and 100,muss zwischen 0 und 100 liegen,
|
||||
or its descendants,oder seine Nachkommen,
|
||||
subscription is already cancelled.,abonnement ist bereits storniert.,
|
||||
{0} Account not found against Customer {1}.,{0} Konto für Kunde {1} nicht gefunden.,
|
||||
{0} Transaction(s) Reconciled,{0} Transaktion(en) Abgestimmt,
|
||||
{0} cannot be zero,{0} kann nicht Null sein,
|
||||
{0} is already running for {1},{0} läuft bereits für {1},
|
||||
{0} units of Item {1} is not available in any of the warehouses.,{0} Einheiten des Artikels {1} sind in keinem der Lager verfügbar.,
|
||||
|
||||
|
Can't render this file because it is too large.
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user