Merge pull request #43891 from frappe/version-15-hotfix

chore: release v15
This commit is contained in:
ruthra kumar
2024-10-30 15:23:57 +05:30
committed by GitHub
47 changed files with 8620 additions and 122 deletions

View File

@@ -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) {

View File

@@ -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):

View File

@@ -323,6 +323,7 @@ class PaymentReconciliation(Document):
"posting_date": inv.posting_date,
"currency": inv.currency,
"cost_center": inv.cost_center,
"remarks": inv.remarks,
}
)
)

View File

@@ -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",

View File

@@ -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

View File

@@ -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": []
}
}

View File

@@ -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"),
}
)

View File

@@ -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(

View File

@@ -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 },

View File

@@ -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",

View File

@@ -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:

View File

@@ -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",

View File

@@ -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();

View File

@@ -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):

View File

@@ -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",

View File

@@ -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):

View File

@@ -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"

View File

@@ -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,

View File

@@ -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

View File

@@ -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",
)
)

View File

@@ -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,

View File

@@ -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))
)

View File

@@ -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

View File

@@ -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();
},

View File

@@ -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()

View File

@@ -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"]:

View File

@@ -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))

View File

@@ -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():

View File

@@ -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",
}
);
}

View File

@@ -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)

View File

@@ -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) {

View File

@@ -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))

View File

@@ -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()

View File

@@ -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)

View File

@@ -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",

View File

@@ -29,6 +29,7 @@ erpnext.sales_common = {
query: "erpnext.controllers.queries.get_project_name",
filters: {
customer: doc.customer,
company: doc.company,
},
};
});

View File

@@ -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;

View File

@@ -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);

View File

@@ -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,

View File

@@ -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);
},

View File

@@ -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)

View File

@@ -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(

View File

@@ -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 %}

View File

@@ -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 &amp; Reports</b></span>","<span class=""h4""><b>Stammdaten &amp; 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 &amp; Masters</b></span>","<span class=""h4""><b>Berichte &amp; 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