Merge pull request #37278 from barredterra/translate-accounts-settings-de
fix: german translations of Accounts Settings
diff --git a/.github/workflows/initiate_release.yml b/.github/workflows/initiate_release.yml
index 7034773..e51c194 100644
--- a/.github/workflows/initiate_release.yml
+++ b/.github/workflows/initiate_release.yml
@@ -15,7 +15,7 @@
strategy:
fail-fast: false
matrix:
- version: ["13", "14"]
+ version: ["13", "14", "15"]
steps:
- uses: octokit/request-action@v2.x
diff --git a/erpnext/accounts/doctype/bank_reconciliation_tool/bank_reconciliation_tool.py b/erpnext/accounts/doctype/bank_reconciliation_tool/bank_reconciliation_tool.py
index 9a7a9a3..7e2f763 100644
--- a/erpnext/accounts/doctype/bank_reconciliation_tool/bank_reconciliation_tool.py
+++ b/erpnext/accounts/doctype/bank_reconciliation_tool/bank_reconciliation_tool.py
@@ -18,6 +18,7 @@
get_entries,
)
from erpnext.accounts.utils import get_account_currency, get_balance_on
+from erpnext.setup.utils import get_exchange_rate
class BankReconciliationTool(Document):
@@ -130,7 +131,7 @@
bank_transaction = frappe.db.get_values(
"Bank Transaction",
bank_transaction_name,
- fieldname=["name", "deposit", "withdrawal", "bank_account"],
+ fieldname=["name", "deposit", "withdrawal", "bank_account", "currency"],
as_dict=True,
)[0]
company_account = frappe.get_value("Bank Account", bank_transaction.bank_account, "account")
@@ -144,29 +145,94 @@
)
company = frappe.get_value("Account", company_account, "company")
+ company_default_currency = frappe.get_cached_value("Company", company, "default_currency")
+ company_account_currency = frappe.get_cached_value("Account", company_account, "account_currency")
+ second_account_currency = frappe.get_cached_value("Account", second_account, "account_currency")
+
+ # determine if multi-currency Journal or not
+ is_multi_currency = (
+ True
+ if company_default_currency != company_account_currency
+ or company_default_currency != second_account_currency
+ or company_default_currency != bank_transaction.currency
+ else False
+ )
accounts = []
- # Multi Currency?
- accounts.append(
- {
- "account": second_account,
- "credit_in_account_currency": bank_transaction.deposit,
- "debit_in_account_currency": bank_transaction.withdrawal,
- "party_type": party_type,
- "party": party,
- "cost_center": get_default_cost_center(company),
- }
- )
+ second_account_dict = {
+ "account": second_account,
+ "account_currency": second_account_currency,
+ "credit_in_account_currency": bank_transaction.deposit,
+ "debit_in_account_currency": bank_transaction.withdrawal,
+ "party_type": party_type,
+ "party": party,
+ "cost_center": get_default_cost_center(company),
+ }
- accounts.append(
- {
- "account": company_account,
- "bank_account": bank_transaction.bank_account,
- "credit_in_account_currency": bank_transaction.withdrawal,
- "debit_in_account_currency": bank_transaction.deposit,
- "cost_center": get_default_cost_center(company),
- }
- )
+ company_account_dict = {
+ "account": company_account,
+ "account_currency": company_account_currency,
+ "bank_account": bank_transaction.bank_account,
+ "credit_in_account_currency": bank_transaction.withdrawal,
+ "debit_in_account_currency": bank_transaction.deposit,
+ "cost_center": get_default_cost_center(company),
+ }
+
+ # convert transaction amount to company currency
+ if is_multi_currency:
+ exc_rate = get_exchange_rate(bank_transaction.currency, company_default_currency, posting_date)
+ withdrawal_in_company_currency = flt(exc_rate * abs(bank_transaction.withdrawal))
+ deposit_in_company_currency = flt(exc_rate * abs(bank_transaction.deposit))
+ else:
+ withdrawal_in_company_currency = bank_transaction.withdrawal
+ deposit_in_company_currency = bank_transaction.deposit
+
+ # if second account is of foreign currency, convert and set debit and credit fields.
+ if second_account_currency != company_default_currency:
+ exc_rate = get_exchange_rate(second_account_currency, company_default_currency, posting_date)
+ second_account_dict.update(
+ {
+ "exchange_rate": exc_rate,
+ "credit": deposit_in_company_currency,
+ "debit": withdrawal_in_company_currency,
+ "credit_in_account_currency": flt(deposit_in_company_currency / exc_rate) or 0,
+ "debit_in_account_currency": flt(withdrawal_in_company_currency / exc_rate) or 0,
+ }
+ )
+ else:
+ second_account_dict.update(
+ {
+ "exchange_rate": 1,
+ "credit": deposit_in_company_currency,
+ "debit": withdrawal_in_company_currency,
+ "credit_in_account_currency": deposit_in_company_currency,
+ "debit_in_account_currency": withdrawal_in_company_currency,
+ }
+ )
+
+ # if company account is of foreign currency, convert and set debit and credit fields.
+ if company_account_currency != company_default_currency:
+ exc_rate = get_exchange_rate(company_account_currency, company_default_currency, posting_date)
+ company_account_dict.update(
+ {
+ "exchange_rate": exc_rate,
+ "credit": withdrawal_in_company_currency,
+ "debit": deposit_in_company_currency,
+ }
+ )
+ else:
+ company_account_dict.update(
+ {
+ "exchange_rate": 1,
+ "credit": withdrawal_in_company_currency,
+ "debit": deposit_in_company_currency,
+ "credit_in_account_currency": withdrawal_in_company_currency,
+ "debit_in_account_currency": deposit_in_company_currency,
+ }
+ )
+
+ accounts.append(second_account_dict)
+ accounts.append(company_account_dict)
journal_entry_dict = {
"voucher_type": entry_type,
@@ -176,6 +242,9 @@
"cheque_no": reference_number,
"mode_of_payment": mode_of_payment,
}
+ if is_multi_currency:
+ journal_entry_dict.update({"multi_currency": True})
+
journal_entry = frappe.new_doc("Journal Entry")
journal_entry.update(journal_entry_dict)
journal_entry.set("accounts", accounts)
diff --git a/erpnext/accounts/doctype/bank_transaction/bank_transaction.py b/erpnext/accounts/doctype/bank_transaction/bank_transaction.py
index 6a47562..4649d23 100644
--- a/erpnext/accounts/doctype/bank_transaction/bank_transaction.py
+++ b/erpnext/accounts/doctype/bank_transaction/bank_transaction.py
@@ -89,7 +89,6 @@
- 0 > a: Error: already over-allocated
- clear means: set the latest transaction date as clearance date
"""
- gl_bank_account = frappe.db.get_value("Bank Account", self.bank_account, "account")
remaining_amount = self.unallocated_amount
for payment_entry in self.payment_entries:
if payment_entry.allocated_amount == 0.0:
diff --git a/erpnext/accounts/doctype/payment_ledger_entry/payment_ledger_entry.json b/erpnext/accounts/doctype/payment_ledger_entry/payment_ledger_entry.json
index 9cf2ac6..4ae8135 100644
--- a/erpnext/accounts/doctype/payment_ledger_entry/payment_ledger_entry.json
+++ b/erpnext/accounts/doctype/payment_ledger_entry/payment_ledger_entry.json
@@ -30,7 +30,8 @@
{
"fieldname": "posting_date",
"fieldtype": "Date",
- "label": "Posting Date"
+ "label": "Posting Date",
+ "search_index": 1
},
{
"fieldname": "account_type",
@@ -153,7 +154,7 @@
"in_create": 1,
"index_web_pages_for_search": 1,
"links": [],
- "modified": "2023-06-29 12:24:20.500632",
+ "modified": "2023-10-30 16:15:00.470283",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Payment Ledger Entry",
diff --git a/erpnext/accounts/doctype/payment_reconciliation/payment_reconciliation.js b/erpnext/accounts/doctype/payment_reconciliation/payment_reconciliation.js
index d9f00be..fc90c3d 100644
--- a/erpnext/accounts/doctype/payment_reconciliation/payment_reconciliation.js
+++ b/erpnext/accounts/doctype/payment_reconciliation/payment_reconciliation.js
@@ -229,6 +229,7 @@
this.data = [];
const dialog = new frappe.ui.Dialog({
title: __("Select Difference Account"),
+ size: 'extra-large',
fields: [
{
fieldname: "allocation",
@@ -252,6 +253,13 @@
in_list_view: 1,
read_only: 1
}, {
+ fieldtype:'Date',
+ fieldname:"gain_loss_posting_date",
+ label: __("Posting Date"),
+ in_list_view: 1,
+ reqd: 1,
+ }, {
+
fieldtype:'Link',
options: 'Account',
in_list_view: 1,
@@ -285,6 +293,9 @@
args.forEach(d => {
frappe.model.set_value("Payment Reconciliation Allocation", d.docname,
"difference_account", d.difference_account);
+ frappe.model.set_value("Payment Reconciliation Allocation", d.docname,
+ "gain_loss_posting_date", d.gain_loss_posting_date);
+
});
this.reconcile_payment_entries();
@@ -300,6 +311,7 @@
'reference_name': d.reference_name,
'difference_amount': d.difference_amount,
'difference_account': d.difference_account,
+ 'gain_loss_posting_date': d.gain_loss_posting_date
});
}
});
diff --git a/erpnext/accounts/doctype/payment_reconciliation/payment_reconciliation.py b/erpnext/accounts/doctype/payment_reconciliation/payment_reconciliation.py
index 3285a52..1626f25 100644
--- a/erpnext/accounts/doctype/payment_reconciliation/payment_reconciliation.py
+++ b/erpnext/accounts/doctype/payment_reconciliation/payment_reconciliation.py
@@ -328,6 +328,7 @@
res.difference_amount = self.get_difference_amount(pay, inv, res["allocated_amount"])
res.difference_account = default_exchange_gain_loss_account
res.exchange_rate = inv.get("exchange_rate")
+ res.update({"gain_loss_posting_date": pay.get("posting_date")})
if pay.get("amount") == 0:
entries.append(res)
@@ -434,6 +435,7 @@
"allocated_amount": flt(row.get("allocated_amount")),
"difference_amount": flt(row.get("difference_amount")),
"difference_account": row.get("difference_account"),
+ "difference_posting_date": row.get("gain_loss_posting_date"),
"cost_center": row.get("cost_center"),
}
)
diff --git a/erpnext/accounts/doctype/payment_reconciliation/test_payment_reconciliation.py b/erpnext/accounts/doctype/payment_reconciliation/test_payment_reconciliation.py
index 1d843ab..71bc498 100644
--- a/erpnext/accounts/doctype/payment_reconciliation/test_payment_reconciliation.py
+++ b/erpnext/accounts/doctype/payment_reconciliation/test_payment_reconciliation.py
@@ -14,6 +14,7 @@
from erpnext.accounts.doctype.purchase_invoice.test_purchase_invoice import make_purchase_invoice
from erpnext.accounts.doctype.sales_invoice.test_sales_invoice import create_sales_invoice
from erpnext.accounts.party import get_party_account
+from erpnext.buying.doctype.purchase_order.test_purchase_order import create_purchase_order
from erpnext.stock.doctype.item.test_item import create_item
test_dependencies = ["Item"]
@@ -85,26 +86,44 @@
self.customer5 = make_customer("_Test PR Customer 5", "EUR")
def create_account(self):
- account_name = "Debtors EUR"
- if not frappe.db.get_value(
- "Account", filters={"account_name": account_name, "company": self.company}
- ):
- acc = frappe.new_doc("Account")
- acc.account_name = account_name
- acc.parent_account = "Accounts Receivable - _PR"
- acc.company = self.company
- acc.account_currency = "EUR"
- acc.account_type = "Receivable"
- acc.insert()
- else:
- name = frappe.db.get_value(
- "Account",
- filters={"account_name": account_name, "company": self.company},
- fieldname="name",
- pluck=True,
- )
- acc = frappe.get_doc("Account", name)
- self.debtors_eur = acc.name
+ accounts = [
+ {
+ "attribute": "debtors_eur",
+ "account_name": "Debtors EUR",
+ "parent_account": "Accounts Receivable - _PR",
+ "account_currency": "EUR",
+ "account_type": "Receivable",
+ },
+ {
+ "attribute": "creditors_usd",
+ "account_name": "Payable USD",
+ "parent_account": "Accounts Payable - _PR",
+ "account_currency": "USD",
+ "account_type": "Payable",
+ },
+ ]
+
+ for x in accounts:
+ x = frappe._dict(x)
+ if not frappe.db.get_value(
+ "Account", filters={"account_name": x.account_name, "company": self.company}
+ ):
+ acc = frappe.new_doc("Account")
+ acc.account_name = x.account_name
+ acc.parent_account = x.parent_account
+ acc.company = self.company
+ acc.account_currency = x.account_currency
+ acc.account_type = x.account_type
+ acc.insert()
+ else:
+ name = frappe.db.get_value(
+ "Account",
+ filters={"account_name": x.account_name, "company": self.company},
+ fieldname="name",
+ pluck=True,
+ )
+ acc = frappe.get_doc("Account", name)
+ setattr(self, x.attribute, acc.name)
def create_sales_invoice(
self, qty=1, rate=100, posting_date=nowdate(), do_not_save=False, do_not_submit=False
@@ -151,6 +170,64 @@
payment.posting_date = posting_date
return payment
+ def create_purchase_invoice(
+ self, qty=1, rate=100, posting_date=nowdate(), do_not_save=False, do_not_submit=False
+ ):
+ """
+ Helper function to populate default values in sales invoice
+ """
+ pinv = make_purchase_invoice(
+ qty=qty,
+ rate=rate,
+ company=self.company,
+ customer=self.supplier,
+ item_code=self.item,
+ item_name=self.item,
+ cost_center=self.cost_center,
+ warehouse=self.warehouse,
+ debit_to=self.debit_to,
+ parent_cost_center=self.cost_center,
+ update_stock=0,
+ currency="INR",
+ is_pos=0,
+ is_return=0,
+ return_against=None,
+ income_account=self.income_account,
+ expense_account=self.expense_account,
+ do_not_save=do_not_save,
+ do_not_submit=do_not_submit,
+ )
+ return pinv
+
+ def create_purchase_order(
+ self, qty=1, rate=100, posting_date=nowdate(), do_not_save=False, do_not_submit=False
+ ):
+ """
+ Helper function to populate default values in sales invoice
+ """
+ pord = create_purchase_order(
+ qty=qty,
+ rate=rate,
+ company=self.company,
+ customer=self.supplier,
+ item_code=self.item,
+ item_name=self.item,
+ cost_center=self.cost_center,
+ warehouse=self.warehouse,
+ debit_to=self.debit_to,
+ parent_cost_center=self.cost_center,
+ update_stock=0,
+ currency="INR",
+ is_pos=0,
+ is_return=0,
+ return_against=None,
+ income_account=self.income_account,
+ expense_account=self.expense_account,
+ do_not_save=do_not_save,
+ do_not_submit=do_not_submit,
+ )
+ return pord
+
def clear_old_entries(self):
doctype_list = [
"GL Entry",
@@ -163,13 +240,11 @@
for doctype in doctype_list:
qb.from_(qb.DocType(doctype)).delete().where(qb.DocType(doctype).company == self.company).run()
- def create_payment_reconciliation(self):
+ def create_payment_reconciliation(self, party_is_customer=True):
pr = frappe.new_doc("Payment Reconciliation")
pr.company = self.company
- pr.party_type = (
- self.party_type if hasattr(self, "party_type") and self.party_type else "Customer"
- )
- pr.party = self.customer
+ pr.party_type = "Customer" if party_is_customer else "Supplier"
+ pr.party = self.customer if party_is_customer else self.supplier
pr.receivable_payable_account = get_party_account(pr.party_type, pr.party, pr.company)
pr.from_invoice_date = pr.to_invoice_date = pr.from_payment_date = pr.to_payment_date = nowdate()
return pr
@@ -906,9 +981,13 @@
self.assertEqual(pr.allocation[0].difference_amount, 0)
def test_reconciliation_purchase_invoice_against_return(self):
- pi = make_purchase_invoice(
- supplier="_Test Supplier USD", currency="USD", conversion_rate=50
- ).submit()
+ self.supplier = "_Test Supplier USD"
+ pi = self.create_purchase_invoice(qty=5, rate=50, do_not_submit=True)
+ pi.supplier = self.supplier
+ pi.currency = "USD"
+ pi.conversion_rate = 50
+ pi.credit_to = self.creditors_usd
+ pi.save().submit()
pi_return = frappe.get_doc(pi.as_dict())
pi_return.name = None
@@ -918,11 +997,12 @@
pi_return.items[0].qty = -pi_return.items[0].qty
pi_return.submit()
- self.company = "_Test Company"
- self.party_type = "Supplier"
- self.customer = "_Test Supplier USD"
-
- pr = self.create_payment_reconciliation()
+ pr = frappe.get_doc("Payment Reconciliation")
+ pr.company = self.company
+ pr.party_type = "Supplier"
+ pr.party = self.supplier
+ pr.receivable_payable_account = self.creditors_usd
+ pr.from_invoice_date = pr.to_invoice_date = pr.from_payment_date = pr.to_payment_date = nowdate()
pr.get_unreconciled_entries()
invoices = []
@@ -931,6 +1011,7 @@
if invoice.invoice_number == pi.name:
invoices.append(invoice.as_dict())
break
+
for payment in pr.payments:
if payment.reference_name == pi_return.name:
payments.append(payment.as_dict())
@@ -941,6 +1022,121 @@
# Should not raise frappe.exceptions.ValidationError: Total Debit must be equal to Total Credit.
pr.reconcile()
+ def test_reconciliation_from_purchase_order_to_multiple_invoices(self):
+ """
+ Reconciling advance payment from PO/SO to multiple invoices should not cause overallocation
+ """
+
+ self.supplier = "_Test Supplier"
+
+ pi1 = self.create_purchase_invoice(qty=10, rate=100)
+ pi2 = self.create_purchase_invoice(qty=10, rate=100)
+ po = self.create_purchase_order(qty=20, rate=100)
+ pay = get_payment_entry(po.doctype, po.name)
+ # Overpay Puchase Order
+ pay.paid_amount = 3000
+ pay.save().submit()
+ # assert total allocated and unallocated before reconciliation
+ self.assertEqual(
+ (
+ pay.references[0].reference_doctype,
+ pay.references[0].reference_name,
+ pay.references[0].allocated_amount,
+ ),
+ (po.doctype, po.name, 2000),
+ )
+ self.assertEqual(pay.total_allocated_amount, 2000)
+ self.assertEqual(pay.unallocated_amount, 1000)
+ self.assertEqual(pay.difference_amount, 0)
+
+ pr = self.create_payment_reconciliation(party_is_customer=False)
+ pr.get_unreconciled_entries()
+
+ self.assertEqual(len(pr.invoices), 2)
+ self.assertEqual(len(pr.payments), 2)
+
+ for x in pr.payments:
+ self.assertEqual((x.reference_type, x.reference_name), (pay.doctype, pay.name))
+
+ invoices = [x.as_dict() for x in pr.invoices]
+ payments = [x.as_dict() for x in pr.payments]
+ pr.allocate_entries(frappe._dict({"invoices": invoices, "payments": payments}))
+ # partial allocation on pi1 and full allocate on pi2
+ pr.allocation[0].allocated_amount = 100
+ pr.reconcile()
+
+ # assert references and total allocated and unallocated amount
+ pay.reload()
+ self.assertEqual(len(pay.references), 3)
+ self.assertEqual(
+ (
+ pay.references[0].reference_doctype,
+ pay.references[0].reference_name,
+ pay.references[0].allocated_amount,
+ ),
+ (po.doctype, po.name, 900),
+ )
+ self.assertEqual(
+ (
+ pay.references[1].reference_doctype,
+ pay.references[1].reference_name,
+ pay.references[1].allocated_amount,
+ ),
+ (pi1.doctype, pi1.name, 100),
+ )
+ self.assertEqual(
+ (
+ pay.references[2].reference_doctype,
+ pay.references[2].reference_name,
+ pay.references[2].allocated_amount,
+ ),
+ (pi2.doctype, pi2.name, 1000),
+ )
+ self.assertEqual(pay.total_allocated_amount, 2000)
+ self.assertEqual(pay.unallocated_amount, 1000)
+ self.assertEqual(pay.difference_amount, 0)
+
+ pr.get_unreconciled_entries()
+ self.assertEqual(len(pr.invoices), 1)
+ self.assertEqual(len(pr.payments), 2)
+
+ invoices = [x.as_dict() for x in pr.invoices]
+ payments = [x.as_dict() for x in pr.payments]
+ pr.allocate_entries(frappe._dict({"invoices": invoices, "payments": payments}))
+ pr.reconcile()
+
+ # assert references and total allocated and unallocated amount
+ pay.reload()
+ self.assertEqual(len(pay.references), 3)
+ # PO references should be removed now
+ self.assertEqual(
+ (
+ pay.references[0].reference_doctype,
+ pay.references[0].reference_name,
+ pay.references[0].allocated_amount,
+ ),
+ (pi1.doctype, pi1.name, 100),
+ )
+ self.assertEqual(
+ (
+ pay.references[1].reference_doctype,
+ pay.references[1].reference_name,
+ pay.references[1].allocated_amount,
+ ),
+ (pi2.doctype, pi2.name, 1000),
+ )
+ self.assertEqual(
+ (
+ pay.references[2].reference_doctype,
+ pay.references[2].reference_name,
+ pay.references[2].allocated_amount,
+ ),
+ (pi1.doctype, pi1.name, 900),
+ )
+ self.assertEqual(pay.total_allocated_amount, 2000)
+ self.assertEqual(pay.unallocated_amount, 1000)
+ self.assertEqual(pay.difference_amount, 0)
+
def make_customer(customer_name, currency=None):
if not frappe.db.exists("Customer", customer_name):
diff --git a/erpnext/accounts/doctype/payment_reconciliation_allocation/payment_reconciliation_allocation.json b/erpnext/accounts/doctype/payment_reconciliation_allocation/payment_reconciliation_allocation.json
index ec718aa..5b8556e 100644
--- a/erpnext/accounts/doctype/payment_reconciliation_allocation/payment_reconciliation_allocation.json
+++ b/erpnext/accounts/doctype/payment_reconciliation_allocation/payment_reconciliation_allocation.json
@@ -19,6 +19,7 @@
"is_advance",
"section_break_5",
"difference_amount",
+ "gain_loss_posting_date",
"column_break_7",
"difference_account",
"exchange_rate",
@@ -151,11 +152,16 @@
"fieldtype": "Link",
"label": "Cost Center",
"options": "Cost Center"
+ },
+ {
+ "fieldname": "gain_loss_posting_date",
+ "fieldtype": "Date",
+ "label": "Difference Posting Date"
}
],
"istable": 1,
"links": [],
- "modified": "2023-09-03 07:52:33.684217",
+ "modified": "2023-10-23 10:44:56.066303",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Payment Reconciliation Allocation",
diff --git a/erpnext/accounts/doctype/pos_invoice/test_pos_invoice.py b/erpnext/accounts/doctype/pos_invoice/test_pos_invoice.py
index 887f1ea..982bdc1 100644
--- a/erpnext/accounts/doctype/pos_invoice/test_pos_invoice.py
+++ b/erpnext/accounts/doctype/pos_invoice/test_pos_invoice.py
@@ -771,19 +771,28 @@
)
create_batch_item_with_batch("_BATCH ITEM Test For Reserve", "TestBatch-RS 02")
- make_stock_entry(
+ se = make_stock_entry(
target="_Test Warehouse - _TC",
item_code="_BATCH ITEM Test For Reserve",
- qty=20,
+ qty=30,
basic_rate=100,
- batch_no="TestBatch-RS 02",
)
+ se.reload()
+
+ batch_no = get_batch_from_bundle(se.items[0].serial_and_batch_bundle)
+
+ # POS Invoice 1, for the batch without bundle
pos_inv1 = create_pos_invoice(
- item="_BATCH ITEM Test For Reserve", rate=300, qty=15, batch_no="TestBatch-RS 02"
+ item="_BATCH ITEM Test For Reserve", rate=300, qty=15, do_not_save=1
)
+
+ pos_inv1.items[0].batch_no = batch_no
pos_inv1.save()
pos_inv1.submit()
+ pos_inv1.reload()
+
+ self.assertFalse(pos_inv1.items[0].serial_and_batch_bundle)
batches = get_auto_batch_nos(
frappe._dict(
@@ -792,7 +801,24 @@
)
for batch in batches:
- if batch.batch_no == "TestBatch-RS 02" and batch.warehouse == "_Test Warehouse - _TC":
+ if batch.batch_no == batch_no and batch.warehouse == "_Test Warehouse - _TC":
+ self.assertEqual(batch.qty, 15)
+
+ # POS Invoice 2, for the batch with bundle
+ pos_inv2 = create_pos_invoice(
+ item="_BATCH ITEM Test For Reserve", rate=300, qty=10, batch_no=batch_no
+ )
+ pos_inv2.reload()
+ self.assertTrue(pos_inv2.items[0].serial_and_batch_bundle)
+
+ batches = get_auto_batch_nos(
+ frappe._dict(
+ {"item_code": "_BATCH ITEM Test For Reserve", "warehouse": "_Test Warehouse - _TC"}
+ )
+ )
+
+ for batch in batches:
+ if batch.batch_no == batch_no and batch.warehouse == "_Test Warehouse - _TC":
self.assertEqual(batch.qty, 5)
def test_pos_batch_item_qty_validation(self):
diff --git a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py
index 2f08b65..e1f0f19 100644
--- a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py
+++ b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py
@@ -585,13 +585,11 @@
def get_gl_entries(self, warehouse_account=None):
self.auto_accounting_for_stock = erpnext.is_perpetual_inventory_enabled(self.company)
+
if self.auto_accounting_for_stock:
self.stock_received_but_not_billed = self.get_company_default("stock_received_but_not_billed")
- self.expenses_included_in_valuation = self.get_company_default("expenses_included_in_valuation")
- self.asset_received_but_not_billed = self.get_company_default("asset_received_but_not_billed")
else:
self.stock_received_but_not_billed = None
- self.expenses_included_in_valuation = None
self.negative_expense_to_be_booked = 0.0
gl_entries = []
@@ -913,40 +911,6 @@
)
)
- # If asset is bought through this document and not linked to PR
- if self.update_stock and item.landed_cost_voucher_amount:
- expenses_included_in_asset_valuation = self.get_company_default(
- "expenses_included_in_asset_valuation"
- )
- # Amount added through landed-cost-voucher
- gl_entries.append(
- self.get_gl_dict(
- {
- "account": expenses_included_in_asset_valuation,
- "against": expense_account,
- "cost_center": item.cost_center,
- "remarks": self.get("remarks") or _("Accounting Entry for Stock"),
- "credit": flt(item.landed_cost_voucher_amount),
- "project": item.project or self.project,
- },
- item=item,
- )
- )
-
- gl_entries.append(
- self.get_gl_dict(
- {
- "account": expense_account,
- "against": expenses_included_in_asset_valuation,
- "cost_center": item.cost_center,
- "remarks": self.get("remarks") or _("Accounting Entry for Stock"),
- "debit": flt(item.landed_cost_voucher_amount),
- "project": item.project or self.project,
- },
- item=item,
- )
- )
-
# update gross amount of asset bought through this document
assets = frappe.db.get_all(
"Asset", filters={"purchase_invoice": self.name, "item_code": item.item_code}
@@ -972,10 +936,11 @@
)
stock_rbnb = (
- self.asset_received_but_not_billed
+ self.get_company_default("asset_received_but_not_billed")
if item.is_fixed_asset
else self.stock_received_but_not_billed
)
+
if not negative_expense_booked_in_pr:
gl_entries.append(
self.get_gl_dict(
@@ -1699,6 +1664,7 @@
"po_detail": "purchase_order_item",
"material_request": "material_request",
"material_request_item": "material_request_item",
+ "wip_composite_asset": "wip_composite_asset",
},
"postprocess": update_item,
"condition": lambda doc: abs(doc.received_qty) < abs(doc.qty),
diff --git a/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py
index 1647732..21cc253 100644
--- a/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py
+++ b/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py
@@ -2500,12 +2500,6 @@
"stock_received_but_not_billed",
"Stock Received But Not Billed - _TC1",
)
- frappe.db.set_value(
- "Company",
- "_Test Company 1",
- "expenses_included_in_valuation",
- "Expenses Included In Valuation - _TC1",
- )
# begin test
si = create_sales_invoice(
@@ -2555,6 +2549,7 @@
)
si = frappe.copy_doc(test_records[0])
+ si.customer = "_Test Internal Customer 3"
si.update_stock = 1
si.set_warehouse = "Finished Goods - _TC"
si.set_target_warehouse = "Stores - _TC"
@@ -3698,6 +3693,20 @@
allowed_to_interact_with="_Test Company with perpetual inventory",
)
+ create_internal_customer(
+ customer_name="_Test Internal Customer 3",
+ represents_company="_Test Company",
+ allowed_to_interact_with="_Test Company",
+ )
+
+ account = create_account(
+ account_name="Unrealized Profit",
+ parent_account="Current Liabilities - _TC",
+ company="_Test Company",
+ )
+
+ frappe.db.set_value("Company", "_Test Company", "unrealized_profit_loss_account", account)
+
create_internal_supplier(
supplier_name="_Test Internal Supplier",
represents_company="Wind Power LLC",
diff --git a/erpnext/accounts/party.py b/erpnext/accounts/party.py
index 310e412..16e73ea 100644
--- a/erpnext/accounts/party.py
+++ b/erpnext/accounts/party.py
@@ -5,7 +5,7 @@
from typing import Optional
import frappe
-from frappe import _, msgprint, scrub
+from frappe import _, msgprint, qb, scrub
from frappe.contacts.doctype.address.address import get_company_address, get_default_address
from frappe.core.doctype.user_permission.user_permission import get_permitted_documents
from frappe.model.utils import get_fetch_values
@@ -480,11 +480,19 @@
def get_party_gle_currency(party_type, party, company):
def generator():
- existing_gle_currency = frappe.db.sql(
- """select account_currency from `tabGL Entry`
- where docstatus=1 and company=%(company)s and party_type=%(party_type)s and party=%(party)s
- limit 1""",
- {"company": company, "party_type": party_type, "party": party},
+ gl = qb.DocType("GL Entry")
+ existing_gle_currency = (
+ qb.from_(gl)
+ .select(gl.account_currency)
+ .where(
+ (gl.docstatus == 1)
+ & (gl.company == company)
+ & (gl.party_type == party_type)
+ & (gl.party == party)
+ & (gl.is_cancelled == 0)
+ )
+ .limit(1)
+ .run()
)
return existing_gle_currency[0][0] if existing_gle_currency else None
diff --git a/erpnext/accounts/report/accounts_receivable/accounts_receivable.py b/erpnext/accounts/report/accounts_receivable/accounts_receivable.py
index b9c7a0b..20444f9 100755
--- a/erpnext/accounts/report/accounts_receivable/accounts_receivable.py
+++ b/erpnext/accounts/report/accounts_receivable/accounts_receivable.py
@@ -718,6 +718,7 @@
query = (
qb.from_(ple)
.select(
+ ple.name,
ple.account,
ple.voucher_type,
ple.voucher_no,
@@ -731,13 +732,15 @@
ple.account_currency,
ple.amount,
ple.amount_in_account_currency,
- ple.remarks,
)
.where(ple.delinked == 0)
.where(Criterion.all(self.qb_selection_filter))
.where(Criterion.any(self.or_filters))
)
+ if self.filters.get("show_remarks"):
+ query = query.select(ple.remarks)
+
if self.filters.get("group_by_party"):
query = query.orderby(self.ple.party, self.ple.posting_date)
else:
diff --git a/erpnext/accounts/report/profitability_analysis/profitability_analysis.js b/erpnext/accounts/report/profitability_analysis/profitability_analysis.js
index 4a3d9bb..b6bbd97 100644
--- a/erpnext/accounts/report/profitability_analysis/profitability_analysis.js
+++ b/erpnext/accounts/report/profitability_analysis/profitability_analysis.js
@@ -32,13 +32,6 @@
"label": __("Accounting Dimension"),
"fieldtype": "Link",
"options": "Accounting Dimension",
- "get_query": () =>{
- return {
- filters: {
- "disabled": 0
- }
- }
- }
},
{
"fieldname": "fiscal_year",
diff --git a/erpnext/accounts/report/tax_withholding_details/tax_withholding_details.py b/erpnext/accounts/report/tax_withholding_details/tax_withholding_details.py
index f2ec31c..e842d2e 100644
--- a/erpnext/accounts/report/tax_withholding_details/tax_withholding_details.py
+++ b/erpnext/accounts/report/tax_withholding_details/tax_withholding_details.py
@@ -47,6 +47,7 @@
out = []
for name, details in gle_map.items():
tax_amount, total_amount, grand_total, base_total = 0, 0, 0, 0
+ bill_no, bill_date = "", ""
tax_withholding_category = tax_category_map.get(name)
rate = tax_rate_map.get(tax_withholding_category)
@@ -68,9 +69,12 @@
tax_amount += entry.credit - entry.debit
if net_total_map.get(name):
- if voucher_type == "Journal Entry":
+ if voucher_type == "Journal Entry" and tax_amount and rate:
# back calcalute total amount from rate and tax_amount
- total_amount = grand_total = base_total = tax_amount / (rate / 100)
+ if rate:
+ total_amount = grand_total = base_total = tax_amount / (rate / 100)
+ elif voucher_type == "Purchase Invoice":
+ total_amount, grand_total, base_total, bill_no, bill_date = net_total_map.get(name)
else:
total_amount, grand_total, base_total = net_total_map.get(name)
else:
@@ -96,7 +100,7 @@
row.update(
{
- "section_code": tax_withholding_category,
+ "section_code": tax_withholding_category or "",
"entity_type": party_map.get(party, {}).get(party_type),
"rate": rate,
"total_amount": total_amount,
@@ -106,10 +110,14 @@
"transaction_date": posting_date,
"transaction_type": voucher_type,
"ref_no": name,
+ "supplier_invoice_no": bill_no,
+ "supplier_invoice_date": bill_date,
}
)
out.append(row)
+ out.sort(key=lambda x: x["section_code"])
+
return out
@@ -157,14 +165,14 @@
def get_columns(filters):
pan = "pan" if frappe.db.has_column(filters.party_type, "pan") else "tax_id"
columns = [
- {"label": _(frappe.unscrub(pan)), "fieldname": pan, "fieldtype": "Data", "width": 60},
{
- "label": _(filters.get("party_type")),
- "fieldname": "party",
- "fieldtype": "Dynamic Link",
- "options": "party_type",
- "width": 180,
+ "label": _("Section Code"),
+ "options": "Tax Withholding Category",
+ "fieldname": "section_code",
+ "fieldtype": "Link",
+ "width": 90,
},
+ {"label": _(frappe.unscrub(pan)), "fieldname": pan, "fieldtype": "Data", "width": 60},
]
if filters.naming_series == "Naming Series":
@@ -179,51 +187,60 @@
columns.extend(
[
- {
- "label": _("Date of Transaction"),
- "fieldname": "transaction_date",
- "fieldtype": "Date",
- "width": 100,
- },
- {
- "label": _("Section Code"),
- "options": "Tax Withholding Category",
- "fieldname": "section_code",
- "fieldtype": "Link",
- "width": 90,
- },
{"label": _("Entity Type"), "fieldname": "entity_type", "fieldtype": "Data", "width": 100},
- {
- "label": _("Total Amount"),
- "fieldname": "total_amount",
- "fieldtype": "Float",
- "width": 90,
- },
+ ]
+ )
+ if filters.party_type == "Supplier":
+ columns.extend(
+ [
+ {
+ "label": _("Supplier Invoice No"),
+ "fieldname": "supplier_invoice_no",
+ "fieldtype": "Data",
+ "width": 120,
+ },
+ {
+ "label": _("Supplier Invoice Date"),
+ "fieldname": "supplier_invoice_date",
+ "fieldtype": "Date",
+ "width": 120,
+ },
+ ]
+ )
+
+ columns.extend(
+ [
{
"label": _("TDS Rate %") if filters.get("party_type") == "Supplier" else _("TCS Rate %"),
"fieldname": "rate",
"fieldtype": "Percent",
- "width": 90,
+ "width": 60,
},
{
- "label": _("Tax Amount"),
- "fieldname": "tax_amount",
+ "label": _("Total Amount"),
+ "fieldname": "total_amount",
"fieldtype": "Float",
- "width": 90,
- },
- {
- "label": _("Grand Total"),
- "fieldname": "grand_total",
- "fieldtype": "Float",
- "width": 90,
+ "width": 120,
},
{
"label": _("Base Total"),
"fieldname": "base_total",
"fieldtype": "Float",
- "width": 90,
+ "width": 120,
},
- {"label": _("Transaction Type"), "fieldname": "transaction_type", "width": 100},
+ {
+ "label": _("Tax Amount"),
+ "fieldname": "tax_amount",
+ "fieldtype": "Float",
+ "width": 120,
+ },
+ {
+ "label": _("Grand Total"),
+ "fieldname": "grand_total",
+ "fieldtype": "Float",
+ "width": 120,
+ },
+ {"label": _("Transaction Type"), "fieldname": "transaction_type", "width": 130},
{
"label": _("Reference No."),
"fieldname": "ref_no",
@@ -231,6 +248,12 @@
"options": "transaction_type",
"width": 180,
},
+ {
+ "label": _("Date of Transaction"),
+ "fieldname": "transaction_date",
+ "fieldtype": "Date",
+ "width": 100,
+ },
]
)
@@ -253,27 +276,7 @@
"Tax Withholding Account", {"company": filters.get("company")}, pluck="account"
)
- query_filters = {
- "account": ("in", tds_accounts),
- "posting_date": ("between", [filters.get("from_date"), filters.get("to_date")]),
- "is_cancelled": 0,
- "against": ("not in", bank_accounts),
- }
-
- party = frappe.get_all(filters.get("party_type"), pluck="name")
- or_filters.update({"against": ("in", party), "voucher_type": "Journal Entry"})
-
- if filters.get("party"):
- del query_filters["account"]
- del query_filters["against"]
- or_filters = {"against": filters.get("party"), "party": filters.get("party")}
-
- tds_docs = frappe.get_all(
- "GL Entry",
- filters=query_filters,
- or_filters=or_filters,
- fields=["voucher_no", "voucher_type", "against", "party"],
- )
+ tds_docs = get_tds_docs_query(filters, bank_accounts, tds_accounts).run(as_dict=True)
for d in tds_docs:
if d.voucher_type == "Purchase Invoice":
@@ -309,6 +312,47 @@
)
+def get_tds_docs_query(filters, bank_accounts, tds_accounts):
+ if not tds_accounts:
+ frappe.throw(
+ _("No {0} Accounts found for this company.").format(frappe.bold("Tax Withholding")),
+ title="Accounts Missing Error",
+ )
+ gle = frappe.qb.DocType("GL Entry")
+ query = (
+ frappe.qb.from_(gle)
+ .select("voucher_no", "voucher_type", "against", "party")
+ .where((gle.is_cancelled == 0))
+ )
+
+ if filters.get("from_date"):
+ query = query.where(gle.posting_date >= filters.get("from_date"))
+ if filters.get("to_date"):
+ query = query.where(gle.posting_date <= filters.get("to_date"))
+
+ if bank_accounts:
+ query = query.where(gle.against.notin(bank_accounts))
+
+ if filters.get("party"):
+ party = [filters.get("party")]
+ query = query.where(
+ ((gle.account.isin(tds_accounts) & gle.against.isin(party)))
+ | ((gle.voucher_type == "Journal Entry") & (gle.party == filters.get("party")))
+ | gle.party.isin(party)
+ )
+ else:
+ party = frappe.get_all(filters.get("party_type"), pluck="name")
+ query = query.where(
+ ((gle.account.isin(tds_accounts) & gle.against.isin(party)))
+ | (
+ (gle.voucher_type == "Journal Entry")
+ & ((gle.party_type == filters.get("party_type")) | (gle.party_type == ""))
+ )
+ | gle.party.isin(party)
+ )
+ return query
+
+
def get_journal_entry_party_map(journal_entries):
journal_entry_party_map = {}
for d in frappe.db.get_all(
@@ -335,6 +379,8 @@
"base_tax_withholding_net_total",
"grand_total",
"base_total",
+ "bill_no",
+ "bill_date",
],
"Sales Invoice": ["base_net_total", "grand_total", "base_total"],
"Payment Entry": [
@@ -353,7 +399,13 @@
for entry in entries:
tax_category_map.update({entry.name: entry.tax_withholding_category})
if doctype == "Purchase Invoice":
- value = [entry.base_tax_withholding_net_total, entry.grand_total, entry.base_total]
+ value = [
+ entry.base_tax_withholding_net_total,
+ entry.grand_total,
+ entry.base_total,
+ entry.bill_no,
+ entry.bill_date,
+ ]
elif doctype == "Sales Invoice":
value = [entry.base_net_total, entry.grand_total, entry.base_total]
elif doctype == "Payment Entry":
diff --git a/erpnext/accounts/utils.py b/erpnext/accounts/utils.py
index 555ed4f..1c7052f 100644
--- a/erpnext/accounts/utils.py
+++ b/erpnext/accounts/utils.py
@@ -645,7 +645,7 @@
"outstanding_amount": d.outstanding_amount,
"allocated_amount": d.allocated_amount,
"exchange_rate": d.exchange_rate if d.exchange_gain_loss else payment_entry.get_exchange_rate(),
- "exchange_gain_loss": d.exchange_gain_loss, # only populated from invoice in case of advance allocation
+ "exchange_gain_loss": d.exchange_gain_loss,
"account": d.account,
}
@@ -658,28 +658,29 @@
existing_row.reference_doctype, existing_row.reference_name
).set_total_advance_paid()
- original_row = existing_row.as_dict().copy()
- existing_row.update(reference_details)
+ if d.allocated_amount <= existing_row.allocated_amount:
+ existing_row.allocated_amount -= d.allocated_amount
- if d.allocated_amount < original_row.allocated_amount:
new_row = payment_entry.append("references")
new_row.docstatus = 1
for field in list(reference_details):
- new_row.set(field, original_row[field])
+ new_row.set(field, reference_details[field])
- new_row.allocated_amount = original_row.allocated_amount - d.allocated_amount
else:
new_row = payment_entry.append("references")
new_row.docstatus = 1
new_row.update(reference_details)
payment_entry.flags.ignore_validate_update_after_submit = True
+ payment_entry.clear_unallocated_reference_document_rows()
payment_entry.setup_party_account_field()
payment_entry.set_missing_values()
if not skip_ref_details_update_for_pe:
payment_entry.set_missing_ref_details()
payment_entry.set_amounts()
- payment_entry.make_exchange_gain_loss_journal()
+ payment_entry.make_exchange_gain_loss_journal(
+ frappe._dict({"difference_posting_date": d.difference_posting_date})
+ )
if not do_not_save:
payment_entry.save(ignore_permissions=True)
diff --git a/erpnext/assets/doctype/asset/asset.js b/erpnext/assets/doctype/asset/asset.js
index f0e4c82..d378fbd 100644
--- a/erpnext/assets/doctype/asset/asset.js
+++ b/erpnext/assets/doctype/asset/asset.js
@@ -9,7 +9,6 @@
frm.set_query("item_code", function() {
return {
"filters": {
- "disabled": 0,
"is_fixed_asset": 1,
"is_stock_item": 0
}
diff --git a/erpnext/assets/doctype/asset/asset.json b/erpnext/assets/doctype/asset/asset.json
index c7d08e2..40f51ab 100644
--- a/erpnext/assets/doctype/asset/asset.json
+++ b/erpnext/assets/doctype/asset/asset.json
@@ -221,11 +221,11 @@
"read_only": 1
},
{
+ "depends_on": "eval:!(doc.is_composite_asset && !doc.capitalized_in)",
"fieldname": "gross_purchase_amount",
"fieldtype": "Currency",
"label": "Gross Purchase Amount",
"options": "Company:company:default_currency",
- "read_only": 1,
"read_only_depends_on": "eval:!doc.is_existing_asset",
"reqd": 1
},
@@ -399,6 +399,7 @@
"fieldtype": "Column Break"
},
{
+ "depends_on": "eval:!doc.is_composite_asset && !doc.is_existing_asset",
"fieldname": "purchase_receipt",
"fieldtype": "Link",
"label": "Purchase Receipt",
@@ -416,6 +417,7 @@
"read_only": 1
},
{
+ "depends_on": "eval:!doc.is_composite_asset && !doc.is_existing_asset",
"fieldname": "purchase_invoice",
"fieldtype": "Link",
"label": "Purchase Invoice",
@@ -479,10 +481,11 @@
"read_only": 1
},
{
+ "depends_on": "eval.doc.asset_quantity",
"fieldname": "asset_quantity",
"fieldtype": "Int",
"label": "Asset Quantity",
- "read_only_depends_on": "eval:!doc.is_existing_asset && !doc.is_composite_asset"
+ "read_only": 1
},
{
"fieldname": "depr_entry_posting_status",
@@ -562,9 +565,14 @@
"link_doctype": "Journal Entry",
"link_fieldname": "reference_name",
"table_fieldname": "accounts"
+ },
+ {
+ "group": "Asset Capitalization",
+ "link_doctype": "Asset Capitalization",
+ "link_fieldname": "target_asset"
}
],
- "modified": "2023-10-03 23:28:26.732269",
+ "modified": "2023-10-27 17:03:46.629617",
"modified_by": "Administrator",
"module": "Assets",
"name": "Asset",
@@ -608,4 +616,4 @@
"states": [],
"title_field": "asset_name",
"track_changes": 1
-}
+}
\ No newline at end of file
diff --git a/erpnext/assets/doctype/asset/test_asset.py b/erpnext/assets/doctype/asset/test_asset.py
index 99824b7..d69f5ef 100644
--- a/erpnext/assets/doctype/asset/test_asset.py
+++ b/erpnext/assets/doctype/asset/test_asset.py
@@ -1789,6 +1789,7 @@
"fixed_asset_account": "_Test Fixed Asset - _TC",
"accumulated_depreciation_account": "_Test Accumulated Depreciations - _TC",
"depreciation_expense_account": "_Test Depreciations - _TC",
+ "capital_work_in_progress_account": "CWIP Account - _TC",
},
)
asset_category.append(
diff --git a/erpnext/assets/doctype/asset_capitalization/asset_capitalization.py b/erpnext/assets/doctype/asset_capitalization/asset_capitalization.py
index 0d6f6b4..728764b 100644
--- a/erpnext/assets/doctype/asset_capitalization/asset_capitalization.py
+++ b/erpnext/assets/doctype/asset_capitalization/asset_capitalization.py
@@ -876,12 +876,8 @@
"amount",
]
- pi_items = frappe.get_all(
- "Purchase Invoice Item", filters={"wip_composite_asset": asset}, fields=fields
- )
-
pr_items = frappe.get_all(
"Purchase Receipt Item", filters={"wip_composite_asset": asset}, fields=fields
)
- return pi_items + pr_items
+ return pr_items
diff --git a/erpnext/assets/doctype/asset_maintenance/test_asset_maintenance.py b/erpnext/assets/doctype/asset_maintenance/test_asset_maintenance.py
index 23088c9..a33acfd 100644
--- a/erpnext/assets/doctype/asset_maintenance/test_asset_maintenance.py
+++ b/erpnext/assets/doctype/asset_maintenance/test_asset_maintenance.py
@@ -13,25 +13,22 @@
class TestAssetMaintenance(unittest.TestCase):
def setUp(self):
set_depreciation_settings_in_company()
- create_asset_data()
- create_maintenance_team()
-
- def test_create_asset_maintenance(self):
- pr = make_purchase_receipt(
+ self.pr = make_purchase_receipt(
item_code="Photocopier", qty=1, rate=100000.0, location="Test Location"
)
+ self.asset_name = frappe.db.get_value("Asset", {"purchase_receipt": self.pr.name}, "name")
+ self.asset_doc = frappe.get_doc("Asset", self.asset_name)
- asset_name = frappe.db.get_value("Asset", {"purchase_receipt": pr.name}, "name")
- asset_doc = frappe.get_doc("Asset", asset_name)
+ def test_create_asset_maintenance_with_log(self):
month_end_date = get_last_day(nowdate())
purchase_date = nowdate() if nowdate() != month_end_date else add_days(nowdate(), -15)
- asset_doc.available_for_use_date = purchase_date
- asset_doc.purchase_date = purchase_date
+ self.asset_doc.available_for_use_date = purchase_date
+ self.asset_doc.purchase_date = purchase_date
- asset_doc.calculate_depreciation = 1
- asset_doc.append(
+ self.asset_doc.calculate_depreciation = 1
+ self.asset_doc.append(
"finance_books",
{
"expected_value_after_useful_life": 200,
@@ -42,97 +39,40 @@
},
)
- asset_doc.save()
+ self.asset_doc.save()
- if not frappe.db.exists("Asset Maintenance", "Photocopier"):
- asset_maintenance = frappe.get_doc(
- {
- "doctype": "Asset Maintenance",
- "asset_name": "Photocopier",
- "maintenance_team": "Team Awesome",
- "company": "_Test Company",
- "asset_maintenance_tasks": get_maintenance_tasks(),
- }
- ).insert()
+ asset_maintenance = frappe.get_doc(
+ {
+ "doctype": "Asset Maintenance",
+ "asset_name": self.asset_name,
+ "maintenance_team": "Team Awesome",
+ "company": "_Test Company",
+ "asset_maintenance_tasks": get_maintenance_tasks(),
+ }
+ ).insert()
- next_due_date = calculate_next_due_date(nowdate(), "Monthly")
- self.assertEqual(asset_maintenance.asset_maintenance_tasks[0].next_due_date, next_due_date)
-
- def test_create_asset_maintenance_log(self):
- if not frappe.db.exists("Asset Maintenance Log", "Photocopier"):
- asset_maintenance_log = frappe.get_doc(
- {
- "doctype": "Asset Maintenance Log",
- "asset_maintenance": "Photocopier",
- "task": "Change Oil",
- "completion_date": add_days(nowdate(), 2),
- "maintenance_status": "Completed",
- }
- ).insert()
- asset_maintenance = frappe.get_doc("Asset Maintenance", "Photocopier")
- next_due_date = calculate_next_due_date(asset_maintenance_log.completion_date, "Monthly")
+ next_due_date = calculate_next_due_date(nowdate(), "Monthly")
self.assertEqual(asset_maintenance.asset_maintenance_tasks[0].next_due_date, next_due_date)
+ asset_maintenance_log = frappe.db.get_value(
+ "Asset Maintenance Log",
+ {"asset_maintenance": asset_maintenance.name, "task_name": "Change Oil"},
+ "name",
+ )
-def create_asset_data():
- if not frappe.db.exists("Asset Category", "Equipment"):
- create_asset_category()
-
- if not frappe.db.exists("Location", "Test Location"):
- frappe.get_doc({"doctype": "Location", "location_name": "Test Location"}).insert()
-
- if not frappe.db.exists("Item", "Photocopier"):
- meta = frappe.get_meta("Asset")
- naming_series = meta.get_field("naming_series").options
- frappe.get_doc(
+ asset_maintenance_log_doc = frappe.get_doc("Asset Maintenance Log", asset_maintenance_log)
+ asset_maintenance_log_doc.update(
{
- "doctype": "Item",
- "item_code": "Photocopier",
- "item_name": "Photocopier",
- "item_group": "All Item Groups",
- "company": "_Test Company",
- "is_fixed_asset": 1,
- "is_stock_item": 0,
- "asset_category": "Equipment",
- "auto_create_assets": 1,
- "asset_naming_series": naming_series,
+ "completion_date": add_days(nowdate(), 2),
+ "maintenance_status": "Completed",
}
- ).insert()
+ )
+ asset_maintenance_log_doc.save()
+ next_due_date = calculate_next_due_date(asset_maintenance_log_doc.completion_date, "Monthly")
-def create_maintenance_team():
- user_list = ["marcus@abc.com", "thalia@abc.com", "mathias@abc.com"]
- if not frappe.db.exists("Role", "Technician"):
- frappe.get_doc({"doctype": "Role", "role_name": "Technician"}).insert()
- for user in user_list:
- if not frappe.db.get_value("User", user):
- frappe.get_doc(
- {
- "doctype": "User",
- "email": user,
- "first_name": user,
- "new_password": "password",
- "roles": [{"doctype": "Has Role", "role": "Technician"}],
- }
- ).insert()
-
- if not frappe.db.exists("Asset Maintenance Team", "Team Awesome"):
- frappe.get_doc(
- {
- "doctype": "Asset Maintenance Team",
- "maintenance_manager": "marcus@abc.com",
- "maintenance_team_name": "Team Awesome",
- "company": "_Test Company",
- "maintenance_team_members": get_maintenance_team(user_list),
- }
- ).insert()
-
-
-def get_maintenance_team(user_list):
- return [
- {"team_member": user, "full_name": user, "maintenance_role": "Technician"}
- for user in user_list[1:]
- ]
+ asset_maintenance.reload()
+ self.assertEqual(asset_maintenance.asset_maintenance_tasks[0].next_due_date, next_due_date)
def get_maintenance_tasks():
@@ -156,23 +96,6 @@
]
-def create_asset_category():
- asset_category = frappe.new_doc("Asset Category")
- asset_category.asset_category_name = "Equipment"
- asset_category.total_number_of_depreciations = 3
- asset_category.frequency_of_depreciation = 3
- asset_category.append(
- "accounts",
- {
- "company_name": "_Test Company",
- "fixed_asset_account": "_Test Fixed Asset - _TC",
- "accumulated_depreciation_account": "_Test Accumulated Depreciations - _TC",
- "depreciation_expense_account": "_Test Depreciations - _TC",
- },
- )
- asset_category.insert()
-
-
def set_depreciation_settings_in_company():
company = frappe.get_doc("Company", "_Test Company")
company.accumulated_depreciation_account = "_Test Accumulated Depreciations - _TC"
diff --git a/erpnext/assets/doctype/asset_maintenance/test_records.json b/erpnext/assets/doctype/asset_maintenance/test_records.json
new file mode 100644
index 0000000..8306fad
--- /dev/null
+++ b/erpnext/assets/doctype/asset_maintenance/test_records.json
@@ -0,0 +1,68 @@
+[
+ {
+ "doctype": "Asset Category",
+ "asset_category_name": "Equipment",
+ "total_number_of_depreciations": 3,
+ "frequency_of_depreciation": 3,
+ "accounts": [
+ {
+ "company_name": "_Test Company",
+ "fixed_asset_account": "_Test Fixed Asset - _TC",
+ "accumulated_depreciation_account": "_Test Accumulated Depreciations - _TC",
+ "depreciation_expense_account": "_Test Depreciations - _TC"
+ }
+ ]
+ },
+ {
+ "doctype": "Location",
+ "location_name": "Test Location"
+ },
+ {
+ "doctype": "Role",
+ "role_name": "Technician"
+ },
+ {
+ "doctype": "User",
+ "email": "marcus@abc.com",
+ "first_name": "marcus@abc.com",
+ "new_password": "password",
+ "roles": [{"doctype": "Has Role", "role": "Technician"}]
+ },
+ {
+ "doctype": "User",
+ "email": "thalia@abc.com",
+ "first_name": "thalia@abc.com",
+ "new_password": "password",
+ "roles": [{"doctype": "Has Role", "role": "Technician"}]
+ },
+ {
+ "doctype": "User",
+ "email": "mathias@abc.com",
+ "first_name": "mathias@abc.com",
+ "new_password": "password",
+ "roles": [{"doctype": "Has Role", "role": "Technician"}]
+ },
+ {
+ "doctype": "Asset Maintenance Team",
+ "maintenance_manager": "marcus@abc.com",
+ "maintenance_team_name": "Team Awesome",
+ "company": "_Test Company",
+ "maintenance_team_members": [
+ {"team_member": "marcus@abc.com", "full_name": "marcus@abc.com", "maintenance_role": "Technician"},
+ {"team_member": "thalia@abc.com", "full_name": "thalia@abc.com", "maintenance_role": "Technician"},
+ {"team_member": "mathias@abc.com", "full_name": "mathias@abc.com", "maintenance_role": "Technician"}
+ ]
+ },
+ {
+ "doctype": "Item",
+ "item_code": "Photocopier",
+ "item_name": "Photocopier",
+ "item_group": "All Item Groups",
+ "company": "_Test Company",
+ "is_fixed_asset": 1,
+ "is_stock_item": 0,
+ "asset_category": "Equipment",
+ "auto_create_assets": 1,
+ "asset_naming_series": "ABC.###"
+ }
+]
diff --git a/erpnext/buying/doctype/buying_settings/buying_settings.json b/erpnext/buying/doctype/buying_settings/buying_settings.json
index 71cb01b..0599992 100644
--- a/erpnext/buying/doctype/buying_settings/buying_settings.json
+++ b/erpnext/buying/doctype/buying_settings/buying_settings.json
@@ -16,7 +16,7 @@
"transaction_settings_section",
"po_required",
"pr_required",
- "over_order_allowance",
+ "blanket_order_allowance",
"column_break_12",
"maintain_same_rate",
"set_landed_cost_based_on_purchase_invoice_rate",
@@ -161,17 +161,17 @@
},
{
"default": "0",
- "description": "Percentage you are allowed to order more against the Blanket Order Quantity. For example: If you have a Blanket Order of Quantity 100 units. and your Allowance is 10% then you are allowed to order 110 units.",
- "fieldname": "over_order_allowance",
- "fieldtype": "Float",
- "label": "Over Order Allowance (%)"
- },
- {
- "default": "0",
"description": "While making Purchase Invoice from Purchase Order, use Exchange Rate on Invoice's transaction date rather than inheriting it from Purchase Order. Only applies for Purchase Invoice.",
"fieldname": "use_transaction_date_exchange_rate",
"fieldtype": "Check",
"label": "Use Transaction Date Exchange Rate"
+ },
+ {
+ "default": "0",
+ "description": "Percentage you are allowed to order beyond the Blanket Order quantity.",
+ "fieldname": "blanket_order_allowance",
+ "fieldtype": "Float",
+ "label": "Blanket Order Allowance (%)"
}
],
"icon": "fa fa-cog",
@@ -179,7 +179,7 @@
"index_web_pages_for_search": 1,
"issingle": 1,
"links": [],
- "modified": "2023-10-16 16:22:03.201078",
+ "modified": "2023-10-25 14:03:32.520418",
"modified_by": "Administrator",
"module": "Buying",
"name": "Buying Settings",
diff --git a/erpnext/buying/doctype/purchase_order/purchase_order.py b/erpnext/buying/doctype/purchase_order/purchase_order.py
index 465fe96..961697c 100644
--- a/erpnext/buying/doctype/purchase_order/purchase_order.py
+++ b/erpnext/buying/doctype/purchase_order/purchase_order.py
@@ -556,6 +556,9 @@
"bom": "bom",
"material_request": "material_request",
"material_request_item": "material_request_item",
+ "sales_order": "sales_order",
+ "sales_order_item": "sales_order_item",
+ "wip_composite_asset": "wip_composite_asset",
},
"postprocess": update_item,
"condition": lambda doc: abs(doc.received_qty) < abs(doc.qty)
@@ -632,6 +635,7 @@
"field_map": {
"name": "po_detail",
"parent": "purchase_order",
+ "wip_composite_asset": "wip_composite_asset",
},
"postprocess": update_item,
"condition": lambda doc: (doc.base_amount == 0 or abs(doc.billed_amt) < abs(doc.amount)),
diff --git a/erpnext/buying/doctype/purchase_order_item/purchase_order_item.json b/erpnext/buying/doctype/purchase_order_item/purchase_order_item.json
index 6b29984..b1da97d 100644
--- a/erpnext/buying/doctype/purchase_order_item/purchase_order_item.json
+++ b/erpnext/buying/doctype/purchase_order_item/purchase_order_item.json
@@ -86,6 +86,8 @@
"billed_amt",
"accounting_details",
"expense_account",
+ "column_break_fyqr",
+ "wip_composite_asset",
"manufacture_details",
"manufacturer",
"manufacturer_part_no",
@@ -896,13 +898,23 @@
"fieldname": "apply_tds",
"fieldtype": "Check",
"label": "Apply TDS"
+ },
+ {
+ "fieldname": "wip_composite_asset",
+ "fieldtype": "Link",
+ "label": "WIP Composite Asset",
+ "options": "Asset"
+ },
+ {
+ "fieldname": "column_break_fyqr",
+ "fieldtype": "Column Break"
}
],
"idx": 1,
"index_web_pages_for_search": 1,
"istable": 1,
"links": [],
- "modified": "2023-09-13 16:22:40.825092",
+ "modified": "2023-10-27 15:50:42.655573",
"modified_by": "Administrator",
"module": "Buying",
"name": "Purchase Order Item",
@@ -915,4 +927,4 @@
"sort_order": "DESC",
"states": [],
"track_changes": 1
-}
+}
\ No newline at end of file
diff --git a/erpnext/buying/doctype/supplier/supplier.json b/erpnext/buying/doctype/supplier/supplier.json
index f37db5f..60dd54c 100644
--- a/erpnext/buying/doctype/supplier/supplier.json
+++ b/erpnext/buying/doctype/supplier/supplier.json
@@ -174,7 +174,7 @@
"fieldname": "supplier_type",
"fieldtype": "Select",
"label": "Supplier Type",
- "options": "Company\nIndividual",
+ "options": "Company\nIndividual\nProprietorship\nPartnership",
"reqd": 1
},
{
@@ -485,7 +485,7 @@
"link_fieldname": "party"
}
],
- "modified": "2023-09-25 12:48:21.869563",
+ "modified": "2023-10-19 16:55:15.148325",
"modified_by": "Administrator",
"module": "Buying",
"name": "Supplier",
diff --git a/erpnext/buying/report/supplier_quotation_comparison/supplier_quotation_comparison.js b/erpnext/buying/report/supplier_quotation_comparison/supplier_quotation_comparison.js
index fd73b87..579c0a6 100644
--- a/erpnext/buying/report/supplier_quotation_comparison/supplier_quotation_comparison.js
+++ b/erpnext/buying/report/supplier_quotation_comparison/supplier_quotation_comparison.js
@@ -44,11 +44,6 @@
}
}
}
- else {
- return {
- filters: { "disabled": 0 }
- }
- }
}
},
{
diff --git a/erpnext/controllers/accounts_controller.py b/erpnext/controllers/accounts_controller.py
index cc5d643..6efe631 100644
--- a/erpnext/controllers/accounts_controller.py
+++ b/erpnext/controllers/accounts_controller.py
@@ -1178,7 +1178,9 @@
self.name,
arg.get("referenced_row"),
):
- posting_date = frappe.db.get_value(arg.voucher_type, arg.voucher_no, "posting_date")
+ posting_date = arg.get("difference_posting_date") or frappe.db.get_value(
+ arg.voucher_type, arg.voucher_no, "posting_date"
+ )
je = create_gain_loss_journal(
self.company,
posting_date,
@@ -1261,7 +1263,7 @@
je = create_gain_loss_journal(
self.company,
- self.posting_date,
+ args.get("difference_posting_date") if args else self.posting_date,
self.party_type,
self.party,
party_account,
diff --git a/erpnext/controllers/status_updater.py b/erpnext/controllers/status_updater.py
index 73a248f..d09001c 100644
--- a/erpnext/controllers/status_updater.py
+++ b/erpnext/controllers/status_updater.py
@@ -47,15 +47,15 @@
],
[
"To Bill",
- "eval:(self.per_delivered == 100 or self.skip_delivery_note) and self.per_billed < 100 and self.docstatus == 1",
+ "eval:(self.per_delivered >= 100 or self.skip_delivery_note) and self.per_billed < 100 and self.docstatus == 1",
],
[
"To Deliver",
- "eval:self.per_delivered < 100 and self.per_billed == 100 and self.docstatus == 1 and not self.skip_delivery_note",
+ "eval:self.per_delivered < 100 and self.per_billed >= 100 and self.docstatus == 1 and not self.skip_delivery_note",
],
[
"Completed",
- "eval:(self.per_delivered == 100 or self.skip_delivery_note) and self.per_billed == 100 and self.docstatus == 1",
+ "eval:(self.per_delivered >= 100 or self.skip_delivery_note) and self.per_billed >= 100 and self.docstatus == 1",
],
["Cancelled", "eval:self.docstatus==2"],
["Closed", "eval:self.status=='Closed' and self.docstatus != 2"],
diff --git a/erpnext/controllers/stock_controller.py b/erpnext/controllers/stock_controller.py
index a40976b..a7330ec 100644
--- a/erpnext/controllers/stock_controller.py
+++ b/erpnext/controllers/stock_controller.py
@@ -76,8 +76,6 @@
gl_entries = self.get_gl_entries(warehouse_account)
make_gl_entries(gl_entries, from_repost=from_repost)
- update_regional_gl_entries(gl_entries, self)
-
def validate_serialized_batch(self):
from erpnext.stock.doctype.serial_no.serial_no import get_serial_nos
@@ -1226,8 +1224,3 @@
repost_entries.append(repost_entry)
return repost_entries
-
-
-@erpnext.allow_regional
-def update_regional_gl_entries(gl_list, doc):
- return
diff --git a/erpnext/controllers/tests/test_accounts_controller.py b/erpnext/controllers/tests/test_accounts_controller.py
index 391258f..97d3c5c 100644
--- a/erpnext/controllers/tests/test_accounts_controller.py
+++ b/erpnext/controllers/tests/test_accounts_controller.py
@@ -7,7 +7,7 @@
from frappe import qb
from frappe.query_builder.functions import Sum
from frappe.tests.utils import FrappeTestCase, change_settings
-from frappe.utils import add_days, flt, nowdate
+from frappe.utils import add_days, flt, getdate, nowdate
from erpnext import get_default_cost_center
from erpnext.accounts.doctype.payment_entry.payment_entry import get_payment_entry
@@ -614,6 +614,73 @@
self.assertEqual(exc_je_for_si, [])
self.assertEqual(exc_je_for_pe, [])
+ def test_15_gain_loss_on_different_posting_date(self):
+ # Invoice in Foreign Currency
+ si = self.create_sales_invoice(
+ posting_date=add_days(nowdate(), -2), qty=2, conversion_rate=80, rate=1
+ )
+ # Payment
+ pe = (
+ self.create_payment_entry(posting_date=add_days(nowdate(), -1), amount=2, source_exc_rate=75)
+ .save()
+ .submit()
+ )
+
+ # There should be outstanding in both currencies
+ si.reload()
+ self.assertEqual(si.outstanding_amount, 2)
+ self.assert_ledger_outstanding(si.doctype, si.name, 160.0, 2.0)
+
+ # Reconcile the remaining amount
+ pr = frappe.get_doc("Payment Reconciliation")
+ pr.company = self.company
+ pr.party_type = "Customer"
+ pr.party = self.customer
+ pr.receivable_payable_account = self.debit_usd
+ pr.get_unreconciled_entries()
+ self.assertEqual(len(pr.invoices), 1)
+ self.assertEqual(len(pr.payments), 1)
+ invoices = [x.as_dict() for x in pr.invoices]
+ payments = [x.as_dict() for x in pr.payments]
+ pr.allocate_entries(frappe._dict({"invoices": invoices, "payments": payments}))
+ pr.allocation[0].gain_loss_posting_date = add_days(nowdate(), 1)
+ pr.reconcile()
+
+ # Exchange Gain/Loss Journal should've been created.
+ exc_je_for_si = self.get_journals_for(si.doctype, si.name)
+ exc_je_for_pe = self.get_journals_for(pe.doctype, pe.name)
+ self.assertNotEqual(exc_je_for_si, [])
+ self.assertEqual(len(exc_je_for_si), 1)
+ self.assertEqual(len(exc_je_for_pe), 1)
+ self.assertEqual(exc_je_for_si[0], exc_je_for_pe[0])
+
+ self.assertEqual(
+ frappe.db.get_value("Journal Entry", exc_je_for_si[0].parent, "posting_date"),
+ getdate(add_days(nowdate(), 1)),
+ )
+
+ self.assertEqual(len(pr.invoices), 0)
+ self.assertEqual(len(pr.payments), 0)
+
+ # There should be no outstanding
+ si.reload()
+ self.assertEqual(si.outstanding_amount, 0)
+ self.assert_ledger_outstanding(si.doctype, si.name, 0.0, 0.0)
+
+ # Cancel Payment
+ pe.reload()
+ pe.cancel()
+
+ si.reload()
+ self.assertEqual(si.outstanding_amount, 2)
+ self.assert_ledger_outstanding(si.doctype, si.name, 160.0, 2.0)
+
+ # Exchange Gain/Loss Journal should've been cancelled
+ exc_je_for_si = self.get_journals_for(si.doctype, si.name)
+ exc_je_for_pe = self.get_journals_for(pe.doctype, pe.name)
+ self.assertEqual(exc_je_for_si, [])
+ self.assertEqual(exc_je_for_pe, [])
+
def test_20_journal_against_sales_invoice(self):
# Invoice in Foreign Currency
si = self.create_sales_invoice(qty=1, conversion_rate=80, rate=1)
diff --git a/erpnext/erpnext_integrations/doctype/plaid_settings/plaid_settings.py b/erpnext/erpnext_integrations/doctype/plaid_settings/plaid_settings.py
index 11d5f6a..eb99345 100644
--- a/erpnext/erpnext_integrations/doctype/plaid_settings/plaid_settings.py
+++ b/erpnext/erpnext_integrations/doctype/plaid_settings/plaid_settings.py
@@ -7,7 +7,7 @@
from frappe import _
from frappe.desk.doctype.tag.tag import add_tag
from frappe.model.document import Document
-from frappe.utils import add_months, formatdate, getdate, today
+from frappe.utils import add_months, formatdate, getdate, sbool, today
from plaid.errors import ItemError
from erpnext.accounts.doctype.journal_entry.journal_entry import get_default_bank_cash_account
@@ -237,8 +237,6 @@
deposit = abs(amount)
withdrawal = 0.0
- status = "Pending" if transaction["pending"] == True else "Settled"
-
tags = []
if transaction["category"]:
try:
@@ -247,13 +245,14 @@
except KeyError:
pass
- if not frappe.db.exists("Bank Transaction", dict(transaction_id=transaction["transaction_id"])):
+ if not frappe.db.exists(
+ "Bank Transaction", dict(transaction_id=transaction["transaction_id"])
+ ) and not sbool(transaction["pending"]):
try:
new_transaction = frappe.get_doc(
{
"doctype": "Bank Transaction",
"date": getdate(transaction["date"]),
- "status": status,
"bank_account": bank_account,
"deposit": deposit,
"withdrawal": withdrawal,
diff --git a/erpnext/erpnext_integrations/workspace/erpnext_integrations/erpnext_integrations.json b/erpnext/erpnext_integrations/workspace/erpnext_integrations/erpnext_integrations.json
index 510317f..dfef223 100644
--- a/erpnext/erpnext_integrations/workspace/erpnext_integrations/erpnext_integrations.json
+++ b/erpnext/erpnext_integrations/workspace/erpnext_integrations/erpnext_integrations.json
@@ -195,26 +195,6 @@
{
"hidden": 0,
"is_query_report": 0,
- "label": "GoCardless Settings",
- "link_count": 0,
- "link_to": "GoCardless Settings",
- "link_type": "DocType",
- "onboard": 0,
- "type": "Link"
- },
- {
- "hidden": 0,
- "is_query_report": 0,
- "label": "Mpesa Settings",
- "link_count": 0,
- "link_to": "Mpesa Settings",
- "link_type": "DocType",
- "onboard": 0,
- "type": "Link"
- },
- {
- "hidden": 0,
- "is_query_report": 0,
"label": "Plaid Settings",
"link_count": 0,
"link_to": "Plaid Settings",
@@ -223,7 +203,7 @@
"type": "Link"
}
],
- "modified": "2023-08-29 15:48:59.010704",
+ "modified": "2023-10-31 19:57:32.748726",
"modified_by": "Administrator",
"module": "ERPNext Integrations",
"name": "ERPNext Integrations",
diff --git a/erpnext/manufacturing/doctype/blanket_order/blanket_order.py b/erpnext/manufacturing/doctype/blanket_order/blanket_order.py
index 32f1c36..0135a4f 100644
--- a/erpnext/manufacturing/doctype/blanket_order/blanket_order.py
+++ b/erpnext/manufacturing/doctype/blanket_order/blanket_order.py
@@ -107,7 +107,7 @@
allowance = flt(
frappe.db.get_single_value(
"Selling Settings" if order_doc.doctype == "Sales Order" else "Buying Settings",
- "over_order_allowance",
+ "blanket_order_allowance",
)
)
for bo_name, item_data in order_data.items():
diff --git a/erpnext/manufacturing/doctype/blanket_order/test_blanket_order.py b/erpnext/manufacturing/doctype/blanket_order/test_blanket_order.py
index 58f3c95..e9fc25b 100644
--- a/erpnext/manufacturing/doctype/blanket_order/test_blanket_order.py
+++ b/erpnext/manufacturing/doctype/blanket_order/test_blanket_order.py
@@ -63,7 +63,7 @@
po1.currency = get_company_currency(po1.company)
self.assertEqual(po1.items[0].qty, (bo.items[0].qty - bo.items[0].ordered_qty))
- def test_over_order_allowance(self):
+ def test_blanket_order_allowance(self):
# Sales Order
bo = make_blanket_order(blanket_order_type="Selling", quantity=100)
@@ -74,7 +74,7 @@
so.items[0].qty = 110
self.assertRaises(frappe.ValidationError, so.submit)
- frappe.db.set_single_value("Selling Settings", "over_order_allowance", 10)
+ frappe.db.set_single_value("Selling Settings", "blanket_order_allowance", 10)
so.submit()
# Purchase Order
@@ -87,7 +87,7 @@
po.items[0].qty = 110
self.assertRaises(frappe.ValidationError, po.submit)
- frappe.db.set_single_value("Buying Settings", "over_order_allowance", 10)
+ frappe.db.set_single_value("Buying Settings", "blanket_order_allowance", 10)
po.submit()
diff --git a/erpnext/manufacturing/doctype/bom/bom.py b/erpnext/manufacturing/doctype/bom/bom.py
index 0231668..229f885 100644
--- a/erpnext/manufacturing/doctype/bom/bom.py
+++ b/erpnext/manufacturing/doctype/bom/bom.py
@@ -1196,12 +1196,12 @@
def add_additional_cost(stock_entry, work_order):
# Add non stock items cost in the additional cost
stock_entry.additional_costs = []
- expenses_included_in_valuation = frappe.get_cached_value(
- "Company", work_order.company, "expenses_included_in_valuation"
+ default_expense_account = frappe.get_cached_value(
+ "Company", work_order.company, "default_expense_account"
)
- add_non_stock_items_cost(stock_entry, work_order, expenses_included_in_valuation)
- add_operations_cost(stock_entry, work_order, expenses_included_in_valuation)
+ add_non_stock_items_cost(stock_entry, work_order, default_expense_account)
+ add_operations_cost(stock_entry, work_order, default_expense_account)
def add_non_stock_items_cost(stock_entry, work_order, expense_account):
diff --git a/erpnext/manufacturing/doctype/job_card/job_card_calendar.js b/erpnext/manufacturing/doctype/job_card/job_card_calendar.js
index f4877fd..9e32085 100644
--- a/erpnext/manufacturing/doctype/job_card/job_card_calendar.js
+++ b/erpnext/manufacturing/doctype/job_card/job_card_calendar.js
@@ -10,8 +10,8 @@
},
gantt: {
field_map: {
- "start": "started_time",
- "end": "started_time",
+ "start": "expected_start_date",
+ "end": "expected_end_date",
"id": "name",
"title": "subject",
"color": "color",
diff --git a/erpnext/manufacturing/doctype/job_card/job_card_list.js b/erpnext/manufacturing/doctype/job_card/job_card_list.js
index 5d883bf..99fca95 100644
--- a/erpnext/manufacturing/doctype/job_card/job_card_list.js
+++ b/erpnext/manufacturing/doctype/job_card/job_card_list.js
@@ -1,6 +1,6 @@
frappe.listview_settings['Job Card'] = {
has_indicator_for_draft: true,
-
+ add_fields: ["expected_start_date", "expected_end_date"],
get_indicator: function(doc) {
const status_colors = {
"Work In Progress": "orange",
diff --git a/erpnext/manufacturing/doctype/production_plan/production_plan.py b/erpnext/manufacturing/doctype/production_plan/production_plan.py
index ddd9375..1850d1e 100644
--- a/erpnext/manufacturing/doctype/production_plan/production_plan.py
+++ b/erpnext/manufacturing/doctype/production_plan/production_plan.py
@@ -1735,7 +1735,10 @@
if not item.conversion_factor and item.purchase_uom:
item.conversion_factor = get_uom_conversion_factor(item.item_code, item.purchase_uom)
- item_details.setdefault(item.get("item_code"), item)
+ if details := item_details.get(item.get("item_code")):
+ details.qty += item.get("qty")
+ else:
+ item_details.setdefault(item.get("item_code"), item)
return item_details
diff --git a/erpnext/manufacturing/doctype/production_plan/test_production_plan.py b/erpnext/manufacturing/doctype/production_plan/test_production_plan.py
index 6ab9232..d414988 100644
--- a/erpnext/manufacturing/doctype/production_plan/test_production_plan.py
+++ b/erpnext/manufacturing/doctype/production_plan/test_production_plan.py
@@ -1332,6 +1332,33 @@
self.assertTrue(row.warehouse == mrp_warhouse)
self.assertEqual(row.quantity, 12)
+ def test_mr_qty_for_same_rm_with_different_sub_assemblies(self):
+ from erpnext.manufacturing.doctype.bom.test_bom import create_nested_bom
+
+ bom_tree = {
+ "Fininshed Goods2 For SUB Test": {
+ "SubAssembly2 For SUB Test": {"ChildPart2 For SUB Test": {}},
+ "SubAssembly3 For SUB Test": {"ChildPart2 For SUB Test": {}},
+ }
+ }
+
+ parent_bom = create_nested_bom(bom_tree, prefix="")
+ plan = create_production_plan(
+ item_code=parent_bom.item,
+ planned_qty=1,
+ ignore_existing_ordered_qty=1,
+ do_not_submit=1,
+ skip_available_sub_assembly_item=1,
+ warehouse="_Test Warehouse - _TC",
+ )
+
+ plan.get_sub_assembly_items()
+ plan.make_material_request()
+
+ for row in plan.mr_items:
+ if row.item_code == "ChildPart2 For SUB Test":
+ self.assertEqual(row.quantity, 2)
+
def create_production_plan(**args):
"""
diff --git a/erpnext/manufacturing/doctype/work_order/test_work_order.py b/erpnext/manufacturing/doctype/work_order/test_work_order.py
index c828c87..0ae7657 100644
--- a/erpnext/manufacturing/doctype/work_order/test_work_order.py
+++ b/erpnext/manufacturing/doctype/work_order/test_work_order.py
@@ -494,6 +494,7 @@
"from_time": row.from_time,
"to_time": row.to_time,
"time_in_mins": row.time_in_mins,
+ "completed_qty": 0,
},
)
diff --git a/erpnext/manufacturing/report/bom_operations_time/bom_operations_time.js b/erpnext/manufacturing/report/bom_operations_time/bom_operations_time.js
index 34edb9d..8729775 100644
--- a/erpnext/manufacturing/report/bom_operations_time/bom_operations_time.js
+++ b/erpnext/manufacturing/report/bom_operations_time/bom_operations_time.js
@@ -12,7 +12,7 @@
"options": "Item",
"get_query": () =>{
return {
- filters: { "disabled": 0, "is_stock_item": 1 }
+ filters: { "is_stock_item": 1 }
}
}
},
diff --git a/erpnext/patches.txt b/erpnext/patches.txt
index d59fe0e..78d2c2c 100644
--- a/erpnext/patches.txt
+++ b/erpnext/patches.txt
@@ -316,7 +316,7 @@
execute:frappe.db.set_single_value("Accounts Settings", "merge_similar_account_heads", 0)
erpnext.patches.v14_0.update_reference_type_in_journal_entry_accounts
erpnext.patches.v14_0.update_subscription_details
-execute:frappe.delete_doc_if_exists("Report", "Tax Detail")
+execute:frappe.delete_doc("Report", "Tax Detail", force=True)
erpnext.patches.v15_0.enable_all_leads
erpnext.patches.v14_0.update_company_in_ldc
erpnext.patches.v14_0.set_packed_qty_in_draft_delivery_notes
@@ -340,5 +340,10 @@
execute:frappe.delete_doc("Page", "welcome-to-erpnext")
erpnext.patches.v15_0.delete_payment_gateway_doctypes
erpnext.patches.v14_0.create_accounting_dimensions_in_sales_order_item
+erpnext.patches.v15_0.update_sre_from_voucher_details
+erpnext.patches.v14_0.rename_over_order_allowance_field
+erpnext.patches.v14_0.migrate_delivery_stop_lock_field
+execute:frappe.db.set_single_value("Payment Reconciliation", "invoice_limit", 50)
+execute:frappe.db.set_single_value("Payment Reconciliation", "payment_limit", 50)
# below migration patch should always run last
-erpnext.patches.v14_0.migrate_gl_to_payment_ledger
\ No newline at end of file
+erpnext.patches.v14_0.migrate_gl_to_payment_ledger
diff --git a/erpnext/patches/v12_0/set_expense_account_in_landed_cost_voucher_taxes.py b/erpnext/patches/v12_0/set_expense_account_in_landed_cost_voucher_taxes.py
deleted file mode 100644
index 9588e02..0000000
--- a/erpnext/patches/v12_0/set_expense_account_in_landed_cost_voucher_taxes.py
+++ /dev/null
@@ -1,42 +0,0 @@
-import frappe
-
-
-def execute():
- frappe.reload_doctype("Landed Cost Taxes and Charges")
-
- company_account_map = frappe._dict(
- frappe.db.sql(
- """
- SELECT name, expenses_included_in_valuation from `tabCompany`
- """
- )
- )
-
- for company, account in company_account_map.items():
- frappe.db.sql(
- """
- UPDATE
- `tabLanded Cost Taxes and Charges` t, `tabLanded Cost Voucher` l
- SET
- t.expense_account = %s
- WHERE
- l.docstatus = 1
- AND l.company = %s
- AND t.parent = l.name
- """,
- (account, company),
- )
-
- frappe.db.sql(
- """
- UPDATE
- `tabLanded Cost Taxes and Charges` t, `tabStock Entry` s
- SET
- t.expense_account = %s
- WHERE
- s.docstatus = 1
- AND s.company = %s
- AND t.parent = s.name
- """,
- (account, company),
- )
diff --git a/erpnext/patches/v14_0/migrate_delivery_stop_lock_field.py b/erpnext/patches/v14_0/migrate_delivery_stop_lock_field.py
new file mode 100644
index 0000000..c9ec1e1
--- /dev/null
+++ b/erpnext/patches/v14_0/migrate_delivery_stop_lock_field.py
@@ -0,0 +1,7 @@
+import frappe
+from frappe.model.utils.rename_field import rename_field
+
+
+def execute():
+ if frappe.db.has_column("Delivery Stop", "lock"):
+ rename_field("Delivery Stop", "lock", "locked")
diff --git a/erpnext/patches/v14_0/rename_over_order_allowance_field.py b/erpnext/patches/v14_0/rename_over_order_allowance_field.py
new file mode 100644
index 0000000..a81fe88
--- /dev/null
+++ b/erpnext/patches/v14_0/rename_over_order_allowance_field.py
@@ -0,0 +1,15 @@
+from frappe.model.utils.rename_field import rename_field
+
+
+def execute():
+ rename_field(
+ "Buying Settings",
+ "over_order_allowance",
+ "blanket_order_allowance",
+ )
+
+ rename_field(
+ "Selling Settings",
+ "over_order_allowance",
+ "blanket_order_allowance",
+ )
diff --git a/erpnext/patches/v15_0/update_sre_from_voucher_details.py b/erpnext/patches/v15_0/update_sre_from_voucher_details.py
new file mode 100644
index 0000000..06ba553
--- /dev/null
+++ b/erpnext/patches/v15_0/update_sre_from_voucher_details.py
@@ -0,0 +1,18 @@
+import frappe
+from frappe.query_builder.functions import IfNull
+
+
+def execute():
+ columns = frappe.db.get_table_columns("Stock Reservation Entry")
+
+ if set(["against_pick_list", "against_pick_list_item"]).issubset(set(columns)):
+ sre = frappe.qb.DocType("Stock Reservation Entry")
+ (
+ frappe.qb.update(sre)
+ .set(sre.from_voucher_type, "Pick List")
+ .set(sre.from_voucher_no, sre.against_pick_list)
+ .set(sre.from_voucher_detail_no, sre.against_pick_list_item)
+ .where(
+ (IfNull(sre.against_pick_list, "") != "") & (IfNull(sre.against_pick_list_item, "") != "")
+ )
+ ).run()
diff --git a/erpnext/public/js/controllers/accounts.js b/erpnext/public/js/controllers/accounts.js
index 3545521..7879173 100644
--- a/erpnext/public/js/controllers/accounts.js
+++ b/erpnext/public/js/controllers/accounts.js
@@ -30,7 +30,6 @@
filters: {
"account_type": account_type,
"company": doc.company,
- "disabled": 0
}
}
});
diff --git a/erpnext/selling/doctype/customer/customer.json b/erpnext/selling/doctype/customer/customer.json
index 40cab9f..3b97123 100644
--- a/erpnext/selling/doctype/customer/customer.json
+++ b/erpnext/selling/doctype/customer/customer.json
@@ -134,7 +134,7 @@
"label": "Customer Type",
"oldfieldname": "customer_type",
"oldfieldtype": "Select",
- "options": "Company\nIndividual",
+ "options": "Company\nIndividual\nProprietorship\nPartnership",
"reqd": 1
},
{
@@ -584,7 +584,7 @@
"link_fieldname": "party"
}
],
- "modified": "2023-09-21 12:23:20.706020",
+ "modified": "2023-10-19 16:56:27.327035",
"modified_by": "Administrator",
"module": "Selling",
"name": "Customer",
diff --git a/erpnext/selling/doctype/sales_order/sales_order.js b/erpnext/selling/doctype/sales_order/sales_order.js
index ba8bc33..3ad18da 100644
--- a/erpnext/selling/doctype/sales_order/sales_order.js
+++ b/erpnext/selling/doctype/sales_order/sales_order.js
@@ -87,17 +87,13 @@
frm.events.get_items_from_internal_purchase_order(frm);
}
- if (frm.is_new()) {
+ if (frm.doc.docstatus === 0) {
frappe.db.get_single_value("Stock Settings", "enable_stock_reservation").then((value) => {
- if (value) {
- frappe.db.get_single_value("Stock Settings", "auto_reserve_stock_for_sales_order").then((value) => {
- // If `Reserve Stock on Sales Order Submission` is enabled in Stock Settings, set Reserve Stock to 1 else 0.
- frm.set_value("reserve_stock", value ? 1 : 0);
- })
- } else {
- // If `Stock Reservation` is disabled in Stock Settings, set Reserve Stock to 0 and read only.
+ if (!value) {
+ // If `Stock Reservation` is disabled in Stock Settings, set Reserve Stock to 0 and make the field read-only and hidden.
frm.set_value("reserve_stock", 0);
frm.set_df_property("reserve_stock", "read_only", 1);
+ frm.set_df_property("reserve_stock", "hidden", 1);
}
})
}
diff --git a/erpnext/selling/doctype/sales_order/sales_order.json b/erpnext/selling/doctype/sales_order/sales_order.json
index a74084d..01d047c 100644
--- a/erpnext/selling/doctype/sales_order/sales_order.json
+++ b/erpnext/selling/doctype/sales_order/sales_order.json
@@ -1631,10 +1631,9 @@
{
"default": "0",
"depends_on": "eval: (doc.docstatus == 0 || doc.reserve_stock)",
- "description": "If checked, Stock Reservation Entries will be created on <b>Submit</b>",
+ "description": "If checked, Stock will be reserved on <b>Submit</b>",
"fieldname": "reserve_stock",
"fieldtype": "Check",
- "hidden": 1,
"label": "Reserve Stock",
"no_copy": 1,
"print_hide": 1,
@@ -1645,7 +1644,7 @@
"idx": 105,
"is_submittable": 1,
"links": [],
- "modified": "2023-07-24 08:59:11.599875",
+ "modified": "2023-10-18 12:41:54.813462",
"modified_by": "Administrator",
"module": "Selling",
"name": "Sales Order",
diff --git a/erpnext/selling/doctype/sales_order/sales_order.py b/erpnext/selling/doctype/sales_order/sales_order.py
index b91002e..e4f1a28 100755
--- a/erpnext/selling/doctype/sales_order/sales_order.py
+++ b/erpnext/selling/doctype/sales_order/sales_order.py
@@ -3,6 +3,7 @@
import json
+from typing import Literal
import frappe
import frappe.utils
@@ -216,7 +217,15 @@
def validate_with_previous_doc(self):
super(SalesOrder, self).validate_with_previous_doc(
- {"Quotation": {"ref_dn_field": "prevdoc_docname", "compare_fields": [["company", "="]]}}
+ {
+ "Quotation": {"ref_dn_field": "prevdoc_docname", "compare_fields": [["company", "="]]},
+ "Quotation Item": {
+ "ref_dn_field": "quotation_item",
+ "compare_fields": [["item_code", "="], ["uom", "="], ["conversion_factor", "="]],
+ "is_child_table": True,
+ "allow_duplicate_prev_row_id": True,
+ },
+ }
)
if cint(frappe.db.get_single_value("Selling Settings", "maintain_same_sales_rate")):
@@ -534,14 +543,24 @@
return False
@frappe.whitelist()
- def create_stock_reservation_entries(self, items_details=None, notify=True) -> None:
+ def create_stock_reservation_entries(
+ self,
+ items_details: list[dict] = None,
+ from_voucher_type: Literal["Pick List", "Purchase Receipt"] = None,
+ notify=True,
+ ) -> None:
"""Creates Stock Reservation Entries for Sales Order Items."""
from erpnext.stock.doctype.stock_reservation_entry.stock_reservation_entry import (
create_stock_reservation_entries_for_so_items as create_stock_reservation_entries,
)
- create_stock_reservation_entries(so=self, items_details=items_details, notify=notify)
+ create_stock_reservation_entries(
+ sales_order=self,
+ items_details=items_details,
+ from_voucher_type=from_voucher_type,
+ notify=notify,
+ )
@frappe.whitelist()
def cancel_stock_reservation_entries(self, sre_list=None, notify=True) -> None:
@@ -748,6 +767,8 @@
if target.company_address:
target.update(get_fetch_values("Delivery Note", "company_address", target.company_address))
+ # set target items names to ensure proper linking with packed_items
+ target.set_new_name()
make_packing_list(target)
def condition(doc):
@@ -820,6 +841,7 @@
"postprocess": update_dn_item,
}
},
+ ignore_permissions=True,
)
dn_item.qty = flt(sre.reserved_qty) * flt(dn_item.get("conversion_factor", 1))
diff --git a/erpnext/selling/doctype/sales_order/test_sales_order.py b/erpnext/selling/doctype/sales_order/test_sales_order.py
index 83689a2..d8b5878 100644
--- a/erpnext/selling/doctype/sales_order/test_sales_order.py
+++ b/erpnext/selling/doctype/sales_order/test_sales_order.py
@@ -1784,10 +1784,10 @@
si.submit()
pe.load_from_db()
- self.assertEqual(pe.references[0].reference_name, si.name)
- self.assertEqual(pe.references[0].allocated_amount, 200)
- self.assertEqual(pe.references[1].reference_name, so.name)
- self.assertEqual(pe.references[1].allocated_amount, 300)
+ self.assertEqual(pe.references[0].reference_name, so.name)
+ self.assertEqual(pe.references[0].allocated_amount, 300)
+ self.assertEqual(pe.references[1].reference_name, si.name)
+ self.assertEqual(pe.references[1].allocated_amount, 200)
def test_delivered_item_material_request(self):
"SO -> MR (Manufacture) -> WO. Test if WO Qty is updated in SO."
diff --git a/erpnext/selling/doctype/selling_settings/selling_settings.json b/erpnext/selling/doctype/selling_settings/selling_settings.json
index 6855012..d6829ce 100644
--- a/erpnext/selling/doctype/selling_settings/selling_settings.json
+++ b/erpnext/selling/doctype/selling_settings/selling_settings.json
@@ -25,7 +25,7 @@
"so_required",
"dn_required",
"sales_update_frequency",
- "over_order_allowance",
+ "blanket_order_allowance",
"column_break_5",
"allow_multiple_items",
"allow_against_multiple_purchase_orders",
@@ -184,12 +184,6 @@
"label": "Allow Sales Order Creation For Expired Quotation"
},
{
- "description": "Percentage you are allowed to order more against the Blanket Order Quantity. For example: If you have a Blanket Order of Quantity 100 units. and your Allowance is 10% then you are allowed to order 110 units.",
- "fieldname": "over_order_allowance",
- "fieldtype": "Float",
- "label": "Over Order Allowance (%)"
- },
- {
"default": "0",
"fieldname": "dont_reserve_sales_order_qty_on_sales_return",
"fieldtype": "Check",
@@ -200,6 +194,12 @@
"fieldname": "allow_negative_rates_for_items",
"fieldtype": "Check",
"label": "Allow Negative rates for Items"
+ },
+ {
+ "description": "Percentage you are allowed to sell beyond the Blanket Order quantity.",
+ "fieldname": "blanket_order_allowance",
+ "fieldtype": "Float",
+ "label": "Blanket Order Allowance (%)"
}
],
"icon": "fa fa-cog",
@@ -207,7 +207,7 @@
"index_web_pages_for_search": 1,
"issingle": 1,
"links": [],
- "modified": "2023-08-14 20:33:05.693667",
+ "modified": "2023-10-25 14:03:03.966701",
"modified_by": "Administrator",
"module": "Selling",
"name": "Selling Settings",
diff --git a/erpnext/setup/doctype/company/company.js b/erpnext/setup/doctype/company/company.js
index 4973dab..1bd469b 100644
--- a/erpnext/setup/doctype/company/company.js
+++ b/erpnext/setup/doctype/company/company.js
@@ -40,7 +40,7 @@
filters:{
'warehouse_type' : 'Transit',
'is_group': 0,
- 'company': frm.doc.company
+ 'company': frm.doc.company_name
}
};
});
@@ -221,7 +221,6 @@
["cost_center", {}],
["round_off_cost_center", {}],
["depreciation_cost_center", {}],
- ["expenses_included_in_asset_valuation", {"account_type": "Expenses Included In Asset Valuation"}],
["capital_work_in_progress_account", {"account_type": "Capital Work in Progress"}],
["asset_received_but_not_billed", {"account_type": "Asset Received But Not Billed"}],
["unrealized_profit_loss_account", {"root_type": ["in", ["Liability", "Asset"]]}],
@@ -236,8 +235,6 @@
$.each([
["stock_adjustment_account",
{"root_type": "Expense", "account_type": "Stock Adjustment"}],
- ["expenses_included_in_valuation",
- {"root_type": "Expense", "account_type": "Expenses Included in Valuation"}],
["stock_received_but_not_billed",
{"root_type": "Liability", "account_type": "Stock Received But Not Billed"}],
["service_received_but_not_billed",
diff --git a/erpnext/setup/doctype/company/company.json b/erpnext/setup/doctype/company/company.json
index 24d7da4..b9ff3dd 100644
--- a/erpnext/setup/doctype/company/company.json
+++ b/erpnext/setup/doctype/company/company.json
@@ -80,7 +80,6 @@
"accumulated_depreciation_account",
"depreciation_expense_account",
"series_for_depreciation_entry",
- "expenses_included_in_asset_valuation",
"column_break_40",
"disposal_account",
"depreciation_cost_center",
@@ -103,11 +102,10 @@
"enable_provisional_accounting_for_non_stock_items",
"default_inventory_account",
"stock_adjustment_account",
- "default_in_transit_warehouse",
"column_break_32",
"stock_received_but_not_billed",
"default_provisional_account",
- "expenses_included_in_valuation",
+ "default_in_transit_warehouse",
"dashboard_tab"
],
"fields": [
@@ -470,14 +468,6 @@
"options": "Account"
},
{
- "fieldname": "expenses_included_in_valuation",
- "fieldtype": "Link",
- "ignore_user_permissions": 1,
- "label": "Expenses Included In Valuation",
- "no_copy": 1,
- "options": "Account"
- },
- {
"fieldname": "accumulated_depreciation_account",
"fieldtype": "Link",
"label": "Accumulated Depreciation Account",
@@ -497,12 +487,6 @@
"label": "Series for Asset Depreciation Entry (Journal Entry)"
},
{
- "fieldname": "expenses_included_in_asset_valuation",
- "fieldtype": "Link",
- "label": "Expenses Included In Asset Valuation",
- "options": "Account"
- },
- {
"fieldname": "column_break_40",
"fieldtype": "Column Break"
},
@@ -782,7 +766,7 @@
"image_field": "company_logo",
"is_tree": 1,
"links": [],
- "modified": "2023-09-10 21:53:13.860791",
+ "modified": "2023-10-23 10:19:24.322898",
"modified_by": "Administrator",
"module": "Setup",
"name": "Company",
diff --git a/erpnext/setup/doctype/company/company.py b/erpnext/setup/doctype/company/company.py
index b05696a..3413702 100644
--- a/erpnext/setup/doctype/company/company.py
+++ b/erpnext/setup/doctype/company/company.py
@@ -92,7 +92,6 @@
["Default Income Account", "default_income_account"],
["Stock Received But Not Billed Account", "stock_received_but_not_billed"],
["Stock Adjustment Account", "stock_adjustment_account"],
- ["Expense Included In Valuation Account", "expenses_included_in_valuation"],
]
for account in accounts:
@@ -384,7 +383,6 @@
"depreciation_expense_account": "Depreciation",
"capital_work_in_progress_account": "Capital Work in Progress",
"asset_received_but_not_billed": "Asset Received But Not Billed",
- "expenses_included_in_asset_valuation": "Expenses Included In Asset Valuation",
"default_expense_account": "Cost of Goods Sold",
}
@@ -394,7 +392,6 @@
"stock_received_but_not_billed": "Stock Received But Not Billed",
"default_inventory_account": "Stock",
"stock_adjustment_account": "Stock Adjustment",
- "expenses_included_in_valuation": "Expenses Included In Valuation",
}
)
diff --git a/erpnext/stock/doctype/delivery_note/test_delivery_note.py b/erpnext/stock/doctype/delivery_note/test_delivery_note.py
index d068192..1eecf6d 100644
--- a/erpnext/stock/doctype/delivery_note/test_delivery_note.py
+++ b/erpnext/stock/doctype/delivery_note/test_delivery_note.py
@@ -1230,16 +1230,16 @@
frappe.db.rollback()
frappe.db.set_single_value("Selling Settings", "dont_reserve_sales_order_qty_on_sales_return", 0)
- def non_internal_transfer_delivery_note(self):
+ def test_non_internal_transfer_delivery_note(self):
from erpnext.stock.doctype.warehouse.test_warehouse import create_warehouse
dn = create_delivery_note(do_not_submit=True)
- warehouse = create_warehouse("Internal Transfer Warehouse", dn.company)
- dn.items[0].db_set("target_warehouse", "warehouse")
+ warehouse = create_warehouse("Internal Transfer Warehouse", company=dn.company)
+ dn.items[0].db_set("target_warehouse", warehouse)
dn.reload()
- self.assertEqual(dn.items[0].target_warehouse, warehouse.name)
+ self.assertEqual(dn.items[0].target_warehouse, warehouse)
dn.save()
dn.reload()
diff --git a/erpnext/stock/doctype/delivery_stop/delivery_stop.json b/erpnext/stock/doctype/delivery_stop/delivery_stop.json
index 5610a81..42560e6 100644
--- a/erpnext/stock/doctype/delivery_stop/delivery_stop.json
+++ b/erpnext/stock/doctype/delivery_stop/delivery_stop.json
@@ -1,815 +1,197 @@
{
- "allow_copy": 0,
- "allow_events_in_timeline": 0,
- "allow_guest_to_view": 0,
- "allow_import": 0,
- "allow_rename": 0,
- "beta": 0,
- "creation": "2017-10-16 16:46:28.166950",
- "custom": 0,
- "docstatus": 0,
- "doctype": "DocType",
- "document_type": "",
- "editable_grid": 1,
- "engine": "InnoDB",
+ "actions": [],
+ "creation": "2017-10-16 16:46:28.166950",
+ "doctype": "DocType",
+ "editable_grid": 1,
+ "engine": "InnoDB",
+ "field_order": [
+ "customer",
+ "address",
+ "locked",
+ "column_break_6",
+ "customer_address",
+ "visited",
+ "order_information_section",
+ "delivery_note",
+ "cb_order",
+ "grand_total",
+ "section_break_7",
+ "contact",
+ "email_sent_to",
+ "column_break_7",
+ "customer_contact",
+ "section_break_9",
+ "distance",
+ "estimated_arrival",
+ "lat",
+ "column_break_19",
+ "uom",
+ "lng",
+ "more_information_section",
+ "details"
+ ],
"fields": [
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 2,
- "fieldname": "customer",
- "fieldtype": "Link",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 1,
- "in_standard_filter": 0,
- "label": "Customer",
- "length": 0,
- "no_copy": 0,
- "options": "Customer",
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "columns": 2,
+ "fieldname": "customer",
+ "fieldtype": "Link",
+ "in_list_view": 1,
+ "label": "Customer",
+ "options": "Customer"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "address",
- "fieldtype": "Link",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 1,
- "in_standard_filter": 0,
- "label": "Address Name",
- "length": 0,
- "no_copy": 0,
- "options": "Address",
- "permlevel": 0,
- "precision": "",
- "print_hide": 1,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 1,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "fieldname": "address",
+ "fieldtype": "Link",
+ "in_list_view": 1,
+ "label": "Address Name",
+ "options": "Address",
+ "print_hide": 1,
+ "reqd": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "lock",
- "fieldtype": "Check",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 1,
- "in_standard_filter": 0,
- "label": "Lock",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "default": "0",
+ "fieldname": "locked",
+ "fieldtype": "Check",
+ "in_list_view": 1,
+ "label": "Locked"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "column_break_6",
- "fieldtype": "Column Break",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "fieldname": "column_break_6",
+ "fieldtype": "Column Break"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "customer_address",
- "fieldtype": "Small Text",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Customer Address",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 1,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "fieldname": "customer_address",
+ "fieldtype": "Small Text",
+ "label": "Customer Address",
+ "read_only": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 1,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "depends_on": "eval:doc.docstatus==1",
- "fieldname": "visited",
- "fieldtype": "Check",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Visited",
- "length": 0,
- "no_copy": 1,
- "permlevel": 0,
- "precision": "",
- "print_hide": 1,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "allow_on_submit": 1,
+ "default": "0",
+ "depends_on": "eval:doc.docstatus==1",
+ "fieldname": "visited",
+ "fieldtype": "Check",
+ "label": "Visited",
+ "no_copy": 1,
+ "print_hide": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "order_information_section",
- "fieldtype": "Section Break",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Order Information",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "fieldname": "order_information_section",
+ "fieldtype": "Section Break",
+ "label": "Order Information"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "delivery_note",
- "fieldtype": "Link",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 1,
- "in_standard_filter": 0,
- "label": "Delivery Note",
- "length": 0,
- "no_copy": 1,
- "options": "Delivery Note",
- "permlevel": 0,
- "precision": "",
- "print_hide": 1,
- "print_hide_if_no_value": 0,
- "read_only": 1,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "fieldname": "delivery_note",
+ "fieldtype": "Link",
+ "in_list_view": 1,
+ "label": "Delivery Note",
+ "no_copy": 1,
+ "options": "Delivery Note",
+ "print_hide": 1,
+ "read_only": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "cb_order",
- "fieldtype": "Column Break",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "fieldname": "cb_order",
+ "fieldtype": "Column Break"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "grand_total",
- "fieldtype": "Currency",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Grand Total",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 1,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "fieldname": "grand_total",
+ "fieldtype": "Currency",
+ "label": "Grand Total",
+ "read_only": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "section_break_7",
- "fieldtype": "Section Break",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Contact Information",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "fieldname": "section_break_7",
+ "fieldtype": "Section Break",
+ "label": "Contact Information"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "contact",
- "fieldtype": "Link",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Contact Name",
- "length": 0,
- "no_copy": 0,
- "options": "Contact",
- "permlevel": 0,
- "precision": "",
- "print_hide": 1,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "fieldname": "contact",
+ "fieldtype": "Link",
+ "label": "Contact Name",
+ "options": "Contact",
+ "print_hide": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "email_sent_to",
- "fieldtype": "Data",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Email sent to",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 1,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "fieldname": "email_sent_to",
+ "fieldtype": "Data",
+ "label": "Email sent to",
+ "read_only": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "column_break_7",
- "fieldtype": "Column Break",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "fieldname": "column_break_7",
+ "fieldtype": "Column Break"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "customer_contact",
- "fieldtype": "Small Text",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Customer Contact",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 1,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "fieldname": "customer_contact",
+ "fieldtype": "Small Text",
+ "label": "Customer Contact",
+ "read_only": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "section_break_9",
- "fieldtype": "Section Break",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Dispatch Information",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "fieldname": "section_break_9",
+ "fieldtype": "Section Break",
+ "label": "Dispatch Information"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "distance",
- "fieldtype": "Float",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Distance",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "2",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 1,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "fieldname": "distance",
+ "fieldtype": "Float",
+ "label": "Distance",
+ "precision": "2",
+ "read_only": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "estimated_arrival",
- "fieldtype": "Datetime",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 1,
- "in_standard_filter": 0,
- "label": "Estimated Arrival",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "fieldname": "estimated_arrival",
+ "fieldtype": "Datetime",
+ "in_list_view": 1,
+ "label": "Estimated Arrival"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "lat",
- "fieldtype": "Float",
- "hidden": 1,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Latitude",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "fieldname": "lat",
+ "fieldtype": "Float",
+ "hidden": 1,
+ "label": "Latitude"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "column_break_19",
- "fieldtype": "Column Break",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "fieldname": "column_break_19",
+ "fieldtype": "Column Break"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "default": "",
- "depends_on": "eval:doc.distance",
- "fieldname": "uom",
- "fieldtype": "Link",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "UOM",
- "length": 0,
- "no_copy": 0,
- "options": "UOM",
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 1,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "depends_on": "eval:doc.distance",
+ "fieldname": "uom",
+ "fieldtype": "Link",
+ "label": "UOM",
+ "options": "UOM",
+ "read_only": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "lng",
- "fieldtype": "Float",
- "hidden": 1,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Longitude",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "fieldname": "lng",
+ "fieldtype": "Float",
+ "hidden": 1,
+ "label": "Longitude"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "more_information_section",
- "fieldtype": "Section Break",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "More Information",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "fieldname": "more_information_section",
+ "fieldtype": "Section Break",
+ "label": "More Information"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "details",
- "fieldtype": "Text Editor",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Details",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
+ "fieldname": "details",
+ "fieldtype": "Text Editor",
+ "label": "Details"
}
- ],
- "has_web_view": 0,
- "hide_heading": 0,
- "hide_toolbar": 0,
- "idx": 0,
- "image_view": 0,
- "in_create": 0,
- "is_submittable": 0,
- "issingle": 0,
- "istable": 1,
- "max_attachments": 0,
- "modified": "2018-10-16 05:23:25.661542",
- "modified_by": "Administrator",
- "module": "Stock",
- "name": "Delivery Stop",
- "name_case": "",
- "owner": "Administrator",
- "permissions": [],
- "quick_entry": 1,
- "read_only": 0,
- "read_only_onload": 0,
- "show_name_in_global_search": 0,
- "sort_field": "modified",
- "sort_order": "DESC",
- "track_changes": 1,
- "track_seen": 0,
- "track_views": 0
+ ],
+ "istable": 1,
+ "links": [],
+ "modified": "2023-09-29 09:22:53.435161",
+ "modified_by": "Administrator",
+ "module": "Stock",
+ "name": "Delivery Stop",
+ "owner": "Administrator",
+ "permissions": [],
+ "quick_entry": 1,
+ "sort_field": "modified",
+ "sort_order": "DESC",
+ "states": [],
+ "track_changes": 1
}
\ No newline at end of file
diff --git a/erpnext/stock/doctype/delivery_trip/delivery_trip.js b/erpnext/stock/doctype/delivery_trip/delivery_trip.js
index 4a72d77..158bd0c 100755
--- a/erpnext/stock/doctype/delivery_trip/delivery_trip.js
+++ b/erpnext/stock/doctype/delivery_trip/delivery_trip.js
@@ -64,6 +64,11 @@
})
}, __("Get stops from"));
}
+ frm.add_custom_button(__("Delivery Notes"), function () {
+ frappe.set_route("List", "Delivery Note",
+ {'name': ["in", frm.doc.delivery_stops.map((stop) => {return stop.delivery_note;})]}
+ );
+ }, __("View"));
},
calculate_arrival_time: function (frm) {
diff --git a/erpnext/stock/doctype/delivery_trip/delivery_trip.py b/erpnext/stock/doctype/delivery_trip/delivery_trip.py
index af2f411..c531a87 100644
--- a/erpnext/stock/doctype/delivery_trip/delivery_trip.py
+++ b/erpnext/stock/doctype/delivery_trip/delivery_trip.py
@@ -170,7 +170,7 @@
for stop in self.delivery_stops:
leg.append(stop.customer_address)
- if optimize and stop.lock:
+ if optimize and stop.locked:
route_list.append(leg)
leg = [stop.customer_address]
diff --git a/erpnext/stock/doctype/delivery_trip/test_delivery_trip.py b/erpnext/stock/doctype/delivery_trip/test_delivery_trip.py
index ed699e3..9b8b46e 100644
--- a/erpnext/stock/doctype/delivery_trip/test_delivery_trip.py
+++ b/erpnext/stock/doctype/delivery_trip/test_delivery_trip.py
@@ -46,7 +46,7 @@
self.assertEqual(len(route_list[0]), 4)
def test_unoptimized_route_list_with_locks(self):
- self.delivery_trip.delivery_stops[0].lock = 1
+ self.delivery_trip.delivery_stops[0].locked = 1
self.delivery_trip.save()
route_list = self.delivery_trip.form_route_list(optimize=False)
@@ -65,7 +65,7 @@
self.assertEqual(len(route_list[0]), 4)
def test_optimized_route_list_with_locks(self):
- self.delivery_trip.delivery_stops[0].lock = 1
+ self.delivery_trip.delivery_stops[0].locked = 1
self.delivery_trip.save()
route_list = self.delivery_trip.form_route_list(optimize=True)
diff --git a/erpnext/stock/doctype/item/item.py b/erpnext/stock/doctype/item/item.py
index 9e28199..d8935fe 100644
--- a/erpnext/stock/doctype/item/item.py
+++ b/erpnext/stock/doctype/item/item.py
@@ -255,7 +255,7 @@
# add item taxes from template
for d in template.get("taxes"):
- self.append("taxes", {"item_tax_template": d.item_tax_template})
+ self.append("taxes", d)
# copy re-order table if empty
if not self.get("reorder_levels"):
diff --git a/erpnext/stock/doctype/item_price/item_price.js b/erpnext/stock/doctype/item_price/item_price.js
index ce489ff..8a4b4ee 100644
--- a/erpnext/stock/doctype/item_price/item_price.js
+++ b/erpnext/stock/doctype/item_price/item_price.js
@@ -6,7 +6,6 @@
frm.set_query("item_code", function() {
return {
filters: {
- "disabled": 0,
"has_variants": 0
}
};
diff --git a/erpnext/stock/doctype/landed_cost_voucher/landed_cost_voucher.py b/erpnext/stock/doctype/landed_cost_voucher/landed_cost_voucher.py
index 7f0dc2d..8bbc660 100644
--- a/erpnext/stock/doctype/landed_cost_voucher/landed_cost_voucher.py
+++ b/erpnext/stock/doctype/landed_cost_voucher/landed_cost_voucher.py
@@ -205,7 +205,11 @@
)
docs = frappe.db.get_all(
"Asset",
- filters={receipt_document_type: item.receipt_document, "item_code": item.item_code},
+ filters={
+ receipt_document_type: item.receipt_document,
+ "item_code": item.item_code,
+ "docstatus": ["!=", 2],
+ },
fields=["name", "docstatus"],
)
if not docs or len(docs) != item.qty:
diff --git a/erpnext/stock/doctype/material_request/material_request.py b/erpnext/stock/doctype/material_request/material_request.py
index a51028d..ecdec80 100644
--- a/erpnext/stock/doctype/material_request/material_request.py
+++ b/erpnext/stock/doctype/material_request/material_request.py
@@ -401,6 +401,7 @@
["uom", "uom"],
["sales_order", "sales_order"],
["sales_order_item", "sales_order_item"],
+ ["wip_composite_asset", "wip_composite_asset"],
],
"postprocess": update_item,
"condition": select_item,
diff --git a/erpnext/stock/doctype/material_request_item/material_request_item.json b/erpnext/stock/doctype/material_request_item/material_request_item.json
index c585d6c..9912be1 100644
--- a/erpnext/stock/doctype/material_request_item/material_request_item.json
+++ b/erpnext/stock/doctype/material_request_item/material_request_item.json
@@ -37,6 +37,10 @@
"rate",
"col_break3",
"amount",
+ "accounting_details_section",
+ "expense_account",
+ "column_break_glru",
+ "wip_composite_asset",
"manufacture_details",
"manufacturer",
"manufacturer_part_no",
@@ -50,11 +54,10 @@
"lead_time_date",
"sales_order",
"sales_order_item",
+ "col_break4",
"production_plan",
"material_request_plan_item",
"job_card_item",
- "col_break4",
- "expense_account",
"section_break_46",
"page_break"
],
@@ -454,13 +457,28 @@
"label": "Job Card Item",
"no_copy": 1,
"print_hide": 1
+ },
+ {
+ "fieldname": "accounting_details_section",
+ "fieldtype": "Section Break",
+ "label": "Accounting Details"
+ },
+ {
+ "fieldname": "column_break_glru",
+ "fieldtype": "Column Break"
+ },
+ {
+ "fieldname": "wip_composite_asset",
+ "fieldtype": "Link",
+ "label": "WIP Composite Asset",
+ "options": "Asset"
}
],
"idx": 1,
"index_web_pages_for_search": 1,
"istable": 1,
"links": [],
- "modified": "2023-05-07 20:23:31.250252",
+ "modified": "2023-10-27 15:53:41.444236",
"modified_by": "Administrator",
"module": "Stock",
"name": "Material Request Item",
@@ -471,4 +489,4 @@
"sort_order": "DESC",
"states": [],
"track_changes": 1
-}
+}
\ No newline at end of file
diff --git a/erpnext/stock/doctype/pick_list/pick_list.js b/erpnext/stock/doctype/pick_list/pick_list.js
index ae05b80..7cd171e 100644
--- a/erpnext/stock/doctype/pick_list/pick_list.js
+++ b/erpnext/stock/doctype/pick_list/pick_list.js
@@ -265,7 +265,8 @@
from_date: moment(frm.doc.creation).format('YYYY-MM-DD'),
to_date: to_date,
voucher_type: "Sales Order",
- against_pick_list: frm.doc.name,
+ from_voucher_type: "Pick List",
+ from_voucher_no: frm.doc.name,
}
frappe.set_route("query-report", "Reserved Stock");
}
diff --git a/erpnext/stock/doctype/pick_list/pick_list.py b/erpnext/stock/doctype/pick_list/pick_list.py
index 2fcd102..ed20209 100644
--- a/erpnext/stock/doctype/pick_list/pick_list.py
+++ b/erpnext/stock/doctype/pick_list/pick_list.py
@@ -229,20 +229,27 @@
def create_stock_reservation_entries(self, notify=True) -> None:
"""Creates Stock Reservation Entries for Sales Order Items against Pick List."""
- from erpnext.stock.doctype.stock_reservation_entry.stock_reservation_entry import (
- create_stock_reservation_entries_for_so_items,
- )
-
- so_details = {}
+ so_items_details_map = {}
for location in self.locations:
if location.warehouse and location.sales_order and location.sales_order_item:
- so_details.setdefault(location.sales_order, []).append(location)
+ item_details = {
+ "name": location.sales_order_item,
+ "item_code": location.item_code,
+ "warehouse": location.warehouse,
+ "qty_to_reserve": (flt(location.picked_qty) - flt(location.stock_reserved_qty)),
+ "from_voucher_no": location.parent,
+ "from_voucher_detail_no": location.name,
+ "serial_and_batch_bundle": location.serial_and_batch_bundle,
+ }
+ so_items_details_map.setdefault(location.sales_order, []).append(item_details)
- if so_details:
- for so, locations in so_details.items():
+ if so_items_details_map:
+ for so, items_details in so_items_details_map.items():
so_doc = frappe.get_doc("Sales Order", so)
- create_stock_reservation_entries_for_so_items(
- so=so_doc, items_details=locations, against_pick_list=True, notify=notify
+ so_doc.create_stock_reservation_entries(
+ items_details=items_details,
+ from_voucher_type="Pick List",
+ notify=notify,
)
@frappe.whitelist()
@@ -253,7 +260,9 @@
cancel_stock_reservation_entries,
)
- cancel_stock_reservation_entries(against_pick_list=self.name, notify=notify)
+ cancel_stock_reservation_entries(
+ from_voucher_type="Pick List", from_voucher_no=self.name, notify=notify
+ )
def validate_picked_qty(self, data):
over_delivery_receipt_allowance = 100 + flt(
diff --git a/erpnext/stock/doctype/pick_list/pick_list_dashboard.py b/erpnext/stock/doctype/pick_list/pick_list_dashboard.py
index 0830fa2..29571a5 100644
--- a/erpnext/stock/doctype/pick_list/pick_list_dashboard.py
+++ b/erpnext/stock/doctype/pick_list/pick_list_dashboard.py
@@ -2,7 +2,7 @@
return {
"fieldname": "pick_list",
"non_standard_fieldnames": {
- "Stock Reservation Entry": "against_pick_list",
+ "Stock Reservation Entry": "from_voucher_no",
},
"internal_links": {
"Sales Order": ["locations", "sales_order"],
diff --git a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py
index 9fdb01a..2a4b6f3 100644
--- a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py
+++ b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py
@@ -263,6 +263,7 @@
self.make_gl_entries()
self.repost_future_sle_and_gle()
self.set_consumed_qty_in_subcontract_order()
+ self.reserve_stock_for_sales_order()
def check_next_docstatus(self):
submit_rv = frappe.db.sql(
@@ -491,7 +492,6 @@
return
# divisional loss adjustment
- expenses_included_in_valuation = self.get_company_default("expenses_included_in_valuation")
valuation_amount_as_per_doc = (
flt(outgoing_amount, d.precision("base_net_amount"))
+ flt(item.landed_cost_voucher_amount)
@@ -505,13 +505,10 @@
)
if divisional_loss:
- if self.is_return or flt(item.item_tax_amount):
- loss_account = expenses_included_in_valuation
- else:
- loss_account = (
- self.get_company_default("default_expense_account", ignore_validation=True)
- or stock_asset_rbnb
- )
+ loss_account = (
+ self.get_company_default("default_expense_account", ignore_validation=True)
+ or stock_asset_rbnb
+ )
cost_center = item.cost_center or frappe.get_cached_value(
"Company", self.company, "cost_center"
@@ -545,17 +542,19 @@
d, gl_entries, self.posting_date, d.get("provisional_expense_account")
)
elif flt(d.qty) and (flt(d.valuation_rate) or self.is_return):
- is_asset_pr = any(d.is_fixed_asset for d in self.get("items"))
remarks = self.get("remarks") or _("Accounting Entry for {0}").format(
- "Asset" if is_asset_pr else "Stock"
+ "Asset" if d.is_fixed_asset else "Stock"
)
- if not (erpnext.is_perpetual_inventory_enabled(self.company) or is_asset_pr):
- return
+ if not (
+ (erpnext.is_perpetual_inventory_enabled(self.company) and d.item_code in stock_items)
+ or d.is_fixed_asset
+ ):
+ continue
stock_asset_rbnb = (
self.get_company_default("asset_received_but_not_billed")
- if is_asset_pr
+ if d.is_fixed_asset
else self.get_company_default("stock_received_but_not_billed")
)
landed_cost_entries = get_item_account_wise_additional_cost(self.name)
@@ -684,10 +683,8 @@
if negative_expense_to_be_booked and valuation_tax:
# Backward compatibility:
- # If expenses_included_in_valuation account has been credited in against PI
# and charges added via Landed Cost Voucher,
# post valuation related charges on "Stock Received But Not Billed"
- # introduced in 2014 for backward compatibility of expenses already booked in expenses_included_in_valuation account
against_account = ", ".join([d.account for d in gl_entries if flt(d.debit) > 0])
total_valuation_amount = sum(valuation_tax.values())
amount_including_divisional_loss = negative_expense_to_be_booked
@@ -763,7 +760,36 @@
pr_doc = self if (pr == self.name) else frappe.get_doc("Purchase Receipt", pr)
update_billing_percentage(pr_doc, update_modified=update_modified)
- self.load_from_db()
+ def reserve_stock_for_sales_order(self):
+ if self.is_return or not cint(
+ frappe.db.get_single_value("Stock Settings", "auto_reserve_stock_for_sales_order_on_purchase")
+ ):
+ return
+
+ self.reload() # reload to get the Serial and Batch Bundle Details
+
+ so_items_details_map = {}
+ for item in self.items:
+ if item.sales_order and item.sales_order_item:
+ item_details = {
+ "name": item.sales_order_item,
+ "item_code": item.item_code,
+ "warehouse": item.warehouse,
+ "qty_to_reserve": item.stock_qty,
+ "from_voucher_no": item.parent,
+ "from_voucher_detail_no": item.name,
+ "serial_and_batch_bundle": item.serial_and_batch_bundle,
+ }
+ so_items_details_map.setdefault(item.sales_order, []).append(item_details)
+
+ if so_items_details_map:
+ for so, items_details in so_items_details_map.items():
+ so_doc = frappe.get_doc("Sales Order", so)
+ so_doc.create_stock_reservation_entries(
+ items_details=items_details,
+ from_voucher_type="Purchase Receipt",
+ notify=True,
+ )
def get_stock_value_difference(voucher_no, voucher_detail_no, warehouse):
@@ -1043,6 +1069,7 @@
"is_fixed_asset": "is_fixed_asset",
"asset_location": "asset_location",
"asset_category": "asset_category",
+ "wip_composite_asset": "wip_composite_asset",
},
"postprocess": update_item,
"filter": lambda d: get_pending_qty(d)[0] <= 0
diff --git a/erpnext/stock/doctype/purchase_receipt/purchase_receipt_dashboard.py b/erpnext/stock/doctype/purchase_receipt/purchase_receipt_dashboard.py
index b3ae7b5..71489fb 100644
--- a/erpnext/stock/doctype/purchase_receipt/purchase_receipt_dashboard.py
+++ b/erpnext/stock/doctype/purchase_receipt/purchase_receipt_dashboard.py
@@ -10,6 +10,7 @@
"Landed Cost Voucher": "receipt_document",
"Auto Repeat": "reference_document",
"Purchase Receipt": "return_against",
+ "Stock Reservation Entry": "from_voucher_no",
},
"internal_links": {
"Material Request": ["items", "material_request"],
@@ -18,7 +19,10 @@
"Quality Inspection": ["items", "quality_inspection"],
},
"transactions": [
- {"label": _("Related"), "items": ["Purchase Invoice", "Landed Cost Voucher", "Asset"]},
+ {
+ "label": _("Related"),
+ "items": ["Purchase Invoice", "Landed Cost Voucher", "Asset", "Stock Reservation Entry"],
+ },
{
"label": _("Reference"),
"items": ["Material Request", "Purchase Order", "Quality Inspection", "Project"],
diff --git a/erpnext/stock/doctype/purchase_receipt/test_purchase_receipt.py b/erpnext/stock/doctype/purchase_receipt/test_purchase_receipt.py
index 1af7b9a..146cbff 100644
--- a/erpnext/stock/doctype/purchase_receipt/test_purchase_receipt.py
+++ b/erpnext/stock/doctype/purchase_receipt/test_purchase_receipt.py
@@ -958,17 +958,33 @@
pr1.cancel()
def test_stock_transfer_from_purchase_receipt(self):
+ from erpnext.stock.doctype.delivery_note.delivery_note import make_inter_company_purchase_receipt
+ from erpnext.stock.doctype.delivery_note.test_delivery_note import create_delivery_note
+
+ prepare_data_for_internal_transfer()
+
+ customer = "_Test Internal Customer 2"
+ company = "_Test Company with perpetual inventory"
+
pr1 = make_purchase_receipt(
- warehouse="Work In Progress - TCP1", company="_Test Company with perpetual inventory"
+ warehouse="Stores - TCP1", company="_Test Company with perpetual inventory"
)
- pr = make_purchase_receipt(
- company="_Test Company with perpetual inventory", warehouse="Stores - TCP1", do_not_save=1
+ dn1 = create_delivery_note(
+ item_code=pr1.items[0].item_code,
+ company=company,
+ customer=customer,
+ cost_center="Main - TCP1",
+ expense_account="Cost of Goods Sold - TCP1",
+ qty=5,
+ rate=500,
+ warehouse="Stores - TCP1",
+ target_warehouse="Work In Progress - TCP1",
)
- pr.supplier_warehouse = ""
+ pr = make_inter_company_purchase_receipt(dn1.name)
pr.items[0].from_warehouse = "Work In Progress - TCP1"
-
+ pr.items[0].warehouse = "Stores - TCP1"
pr.submit()
gl_entries = get_gl_entries("Purchase Receipt", pr.name)
@@ -982,9 +998,13 @@
self.assertEqual(expected_sle[sle.warehouse], sle.actual_qty)
pr.cancel()
- pr1.cancel()
def test_stock_transfer_from_purchase_receipt_with_valuation(self):
+ from erpnext.stock.doctype.delivery_note.delivery_note import make_inter_company_purchase_receipt
+ from erpnext.stock.doctype.delivery_note.test_delivery_note import create_delivery_note
+
+ prepare_data_for_internal_transfer()
+
create_warehouse(
"_Test Warehouse for Valuation",
company="_Test Company with perpetual inventory",
@@ -992,16 +1012,28 @@
)
pr1 = make_purchase_receipt(
- warehouse="_Test Warehouse for Valuation - TCP1",
+ warehouse="Stores - TCP1",
company="_Test Company with perpetual inventory",
)
- pr = make_purchase_receipt(
- company="_Test Company with perpetual inventory", warehouse="Stores - TCP1", do_not_save=1
+ customer = "_Test Internal Customer 2"
+ company = "_Test Company with perpetual inventory"
+
+ dn1 = create_delivery_note(
+ item_code=pr1.items[0].item_code,
+ company=company,
+ customer=customer,
+ cost_center="Main - TCP1",
+ expense_account="Cost of Goods Sold - TCP1",
+ qty=5,
+ rate=50,
+ warehouse="Stores - TCP1",
+ target_warehouse="_Test Warehouse for Valuation - TCP1",
)
+ pr = make_inter_company_purchase_receipt(dn1.name)
pr.items[0].from_warehouse = "_Test Warehouse for Valuation - TCP1"
- pr.supplier_warehouse = ""
+ pr.items[0].warehouse = "Stores - TCP1"
pr.append(
"taxes",
@@ -1037,7 +1069,6 @@
self.assertEqual(gle.credit, expected_gle[i][2])
pr.cancel()
- pr1.cancel()
def test_po_to_pi_and_po_to_pr_worflow_full(self):
"""Test following behaviour:
diff --git a/erpnext/stock/doctype/purchase_receipt_item/purchase_receipt_item.json b/erpnext/stock/doctype/purchase_receipt_item/purchase_receipt_item.json
index d93d21c..718f007 100644
--- a/erpnext/stock/doctype/purchase_receipt_item/purchase_receipt_item.json
+++ b/erpnext/stock/doctype/purchase_receipt_item/purchase_receipt_item.json
@@ -125,7 +125,9 @@
"dimension_col_break",
"cost_center",
"section_break_80",
- "page_break"
+ "page_break",
+ "sales_order",
+ "sales_order_item"
],
"fields": [
{
@@ -898,7 +900,8 @@
"label": "Delivery Note Item",
"no_copy": 1,
"print_hide": 1,
- "read_only": 1
+ "read_only": 1,
+ "search_index": 1
},
{
"collapsible": 1,
@@ -1062,12 +1065,32 @@
"fieldtype": "Link",
"label": "WIP Composite Asset",
"options": "Asset"
+ },
+ {
+ "fieldname": "sales_order",
+ "fieldtype": "Link",
+ "label": "Sales Order",
+ "no_copy": 1,
+ "options": "Sales Order",
+ "print_hide": 1,
+ "read_only": 1,
+ "search_index": 1
+ },
+ {
+ "fieldname": "sales_order_item",
+ "fieldtype": "Data",
+ "hidden": 1,
+ "label": "Sales Order Item",
+ "no_copy": 1,
+ "print_hide": 1,
+ "read_only": 1,
+ "search_index": 1
}
],
"idx": 1,
"istable": 1,
"links": [],
- "modified": "2023-10-03 21:11:50.547261",
+ "modified": "2023-10-30 17:32:24.560337",
"modified_by": "Administrator",
"module": "Stock",
"name": "Purchase Receipt Item",
@@ -1078,4 +1101,4 @@
"sort_field": "modified",
"sort_order": "DESC",
"states": []
-}
+}
\ No newline at end of file
diff --git a/erpnext/stock/doctype/quality_inspection_template/test_records.json b/erpnext/stock/doctype/quality_inspection_template/test_records.json
index 980f49a..2da99f6 100644
--- a/erpnext/stock/doctype/quality_inspection_template/test_records.json
+++ b/erpnext/stock/doctype/quality_inspection_template/test_records.json
@@ -1,5 +1,9 @@
[
{
+ "doctype": "Quality Inspection Parameter",
+ "parameter" : "_Test Param"
+ },
+ {
"quality_inspection_template_name" : "_Test Quality Inspection Template",
"doctype": "Quality Inspection Template",
"item_quality_inspection_parameter" : [
diff --git a/erpnext/stock/doctype/repost_item_valuation/test_repost_item_valuation.py b/erpnext/stock/doctype/repost_item_valuation/test_repost_item_valuation.py
index 1853f45..623e8fa 100644
--- a/erpnext/stock/doctype/repost_item_valuation/test_repost_item_valuation.py
+++ b/erpnext/stock/doctype/repost_item_valuation/test_repost_item_valuation.py
@@ -137,8 +137,6 @@
item_code="_Test Item",
warehouse="_Test Warehouse - _TC",
based_on="Item and Warehouse",
- voucher_type="Sales Invoice",
- voucher_no="SI-1",
posting_date="2021-01-02",
posting_time="00:01:00",
)
@@ -148,8 +146,6 @@
riv1.flags.dont_run_in_test = True
riv1.submit()
_assert_status(riv1, "Queued")
- self.assertEqual(riv1.voucher_type, "Sales Invoice") # traceability
- self.assertEqual(riv1.voucher_no, "SI-1")
# newer than existing duplicate - riv1
riv2 = frappe.get_doc(riv_args.update({"posting_date": "2021-01-03"}))
diff --git a/erpnext/stock/doctype/serial_and_batch_bundle/serial_and_batch_bundle.py b/erpnext/stock/doctype/serial_and_batch_bundle/serial_and_batch_bundle.py
index 96e4a55..f96c184 100644
--- a/erpnext/stock/doctype/serial_and_batch_bundle/serial_and_batch_bundle.py
+++ b/erpnext/stock/doctype/serial_and_batch_bundle/serial_and_batch_bundle.py
@@ -658,7 +658,7 @@
if not available_batches:
return
- available_batches = get_availabel_batches_qty(available_batches)
+ available_batches = get_available_batches_qty(available_batches)
for batch_no in batches:
if batch_no not in available_batches or available_batches[batch_no] < 0:
self.throw_error_message(
@@ -1074,7 +1074,7 @@
return get_auto_batch_nos(kwargs)
-def get_availabel_batches_qty(available_batches):
+def get_available_batches_qty(available_batches):
available_batches_qty = defaultdict(float)
for batch in available_batches:
available_batches_qty[batch.batch_no] += batch.qty
@@ -1301,6 +1301,7 @@
"POS Invoice",
fields=[
"`tabPOS Invoice Item`.batch_no",
+ "`tabPOS Invoice Item`.qty",
"`tabPOS Invoice`.is_return",
"`tabPOS Invoice Item`.warehouse",
"`tabPOS Invoice Item`.name as child_docname",
@@ -1321,9 +1322,6 @@
if pos_invoice.serial_and_batch_bundle
]
- if not ids:
- return {}
-
if ids:
for d in get_serial_batch_ledgers(kwargs.item_code, docstatus=1, name=ids):
key = (d.batch_no, d.warehouse)
@@ -1337,6 +1335,7 @@
else:
pos_batches[key].qty += d.qty
+ # POS invoices having batch without bundle (to handle old POS invoices)
for row in pos_invoices:
if not row.batch_no:
continue
@@ -1346,11 +1345,11 @@
key = (row.batch_no, row.warehouse)
if key in pos_batches:
- pos_batches[key] -= row.qty * -1 if row.is_return else row.qty
+ pos_batches[key]["qty"] -= row.qty * -1 if row.is_return else row.qty
else:
pos_batches[key] = frappe._dict(
{
- "qty": (row.qty * -1 if row.is_return else row.qty),
+ "qty": (row.qty * -1 if not row.is_return else row.qty),
"warehouse": row.warehouse,
}
)
diff --git a/erpnext/stock/doctype/stock_entry/stock_entry.py b/erpnext/stock/doctype/stock_entry/stock_entry.py
index a2cae7f..c41349f 100644
--- a/erpnext/stock/doctype/stock_entry/stock_entry.py
+++ b/erpnext/stock/doctype/stock_entry/stock_entry.py
@@ -438,31 +438,37 @@
item_code.append(item.item_code)
def validate_fg_completed_qty(self):
- item_wise_qty = {}
- if self.purpose == "Manufacture" and self.work_order:
- for d in self.items:
- if d.is_finished_item:
- if self.process_loss_qty:
- d.qty = self.fg_completed_qty - self.process_loss_qty
+ if self.purpose != "Manufacture":
+ return
- item_wise_qty.setdefault(d.item_code, []).append(d.qty)
+ fg_qty = defaultdict(float)
+ for d in self.items:
+ if d.is_finished_item:
+ fg_qty[d.item_code] += flt(d.qty)
+
+ if not fg_qty:
+ return
precision = frappe.get_precision("Stock Entry Detail", "qty")
- for item_code, qty_list in item_wise_qty.items():
- total = flt(sum(qty_list), precision)
+ fg_item = list(fg_qty.keys())[0]
+ fg_item_qty = flt(fg_qty[fg_item], precision)
+ fg_completed_qty = flt(self.fg_completed_qty, precision)
- if (self.fg_completed_qty - total) > 0 and not self.process_loss_qty:
- self.process_loss_qty = flt(self.fg_completed_qty - total, precision)
- self.process_loss_percentage = flt(self.process_loss_qty * 100 / self.fg_completed_qty)
+ for d in self.items:
+ if not fg_qty.get(d.item_code):
+ continue
- if self.process_loss_qty:
- total += flt(self.process_loss_qty, precision)
+ if (fg_completed_qty - fg_item_qty) > 0:
+ self.process_loss_qty = fg_completed_qty - fg_item_qty
- if self.fg_completed_qty != total:
+ if not self.process_loss_qty:
+ continue
+
+ if fg_completed_qty != (flt(fg_item_qty) + flt(self.process_loss_qty, precision)):
frappe.throw(
- _("The finished product {0} quantity {1} and For Quantity {2} cannot be different").format(
- frappe.bold(item_code), frappe.bold(total), frappe.bold(self.fg_completed_qty)
- )
+ _(
+ "Since there is a process loss of {0} units for the finished good {1}, you should reduce the quantity by {0} units for the finished good {1} in the Items Table."
+ ).format(frappe.bold(self.process_loss_qty), frappe.bold(d.item_code))
)
def validate_difference_account(self):
@@ -1014,14 +1020,34 @@
& (se.docstatus == 1)
& (se_detail.item_code == se_item.item_code)
& (
- (se.purchase_order == self.purchase_order)
+ ((se.purchase_order == self.purchase_order) & (se_detail.po_detail == se_item.po_detail))
if self.subcontract_data.order_doctype == "Purchase Order"
- else (se.subcontracting_order == self.subcontracting_order)
+ else (
+ (se.subcontracting_order == self.subcontracting_order)
+ & (se_detail.sco_rm_detail == se_item.sco_rm_detail)
+ )
)
)
- ).run()[0][0]
+ ).run()[0][0] or 0
- if flt(total_supplied, precision) > flt(total_allowed, precision):
+ total_returned = 0
+ if self.subcontract_data.order_doctype == "Subcontracting Order":
+ total_returned = (
+ frappe.qb.from_(se)
+ .inner_join(se_detail)
+ .on(se.name == se_detail.parent)
+ .select(Sum(se_detail.transfer_qty))
+ .where(
+ (se.purpose == "Material Transfer")
+ & (se.docstatus == 1)
+ & (se.is_return == 1)
+ & (se_detail.item_code == se_item.item_code)
+ & (se_detail.sco_rm_detail == se_item.sco_rm_detail)
+ & (se.subcontracting_order == self.subcontracting_order)
+ )
+ ).run()[0][0] or 0
+
+ if flt(total_supplied - total_returned, precision) > flt(total_allowed, precision):
frappe.throw(
_("Row {0}# Item {1} cannot be transferred more than {2} against {3} {4}").format(
se_item.idx,
diff --git a/erpnext/stock/doctype/stock_entry/test_stock_entry.py b/erpnext/stock/doctype/stock_entry/test_stock_entry.py
index cc8a108..3e0610e 100644
--- a/erpnext/stock/doctype/stock_entry/test_stock_entry.py
+++ b/erpnext/stock/doctype/stock_entry/test_stock_entry.py
@@ -449,9 +449,7 @@
repack.posting_date = nowdate()
repack.posting_time = nowtime()
- expenses_included_in_valuation = frappe.get_value(
- "Company", company, "expenses_included_in_valuation"
- )
+ default_expense_account = frappe.get_value("Company", company, "default_expense_account")
items = get_multiple_items()
repack.items = []
@@ -462,12 +460,12 @@
"additional_costs",
[
{
- "expense_account": expenses_included_in_valuation,
+ "expense_account": default_expense_account,
"description": "Actual Operating Cost",
"amount": 1000,
},
{
- "expense_account": expenses_included_in_valuation,
+ "expense_account": default_expense_account,
"description": "Additional Operating Cost",
"amount": 200,
},
@@ -506,9 +504,7 @@
self.check_gl_entries(
"Stock Entry",
repack.name,
- sorted(
- [[stock_in_hand_account, 1200, 0.0], ["Expenses Included In Valuation - TCP1", 0.0, 1200.0]]
- ),
+ sorted([[stock_in_hand_account, 1200, 0.0], ["Cost of Goods Sold - TCP1", 0.0, 1200.0]]),
)
def check_stock_ledger_entries(self, voucher_type, voucher_no, expected_sle):
diff --git a/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.js b/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.js
index 5452692..b3998b7 100644
--- a/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.js
+++ b/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.js
@@ -123,13 +123,6 @@
fieldname: "item_code",
fieldtype: "Link",
options: "Item",
- "get_query": function() {
- return {
- "filters": {
- "disabled": 0,
- }
- };
- }
},
{
label: __("Ignore Empty Stock"),
diff --git a/erpnext/stock/doctype/stock_reservation_entry/stock_reservation_entry.js b/erpnext/stock/doctype/stock_reservation_entry/stock_reservation_entry.js
index c5df319..f60a037 100644
--- a/erpnext/stock/doctype/stock_reservation_entry/stock_reservation_entry.js
+++ b/erpnext/stock/doctype/stock_reservation_entry/stock_reservation_entry.js
@@ -92,7 +92,7 @@
'qty', 'read_only', frm.doc.has_serial_no
);
- frm.set_df_property('sb_entries', 'allow_on_submit', frm.doc.against_pick_list ? 0 : 1);
+ frm.set_df_property('sb_entries', 'allow_on_submit', frm.doc.from_voucher_type == "Pick List" ? 0 : 1);
},
hide_rate_related_fields(frm) {
diff --git a/erpnext/stock/doctype/stock_reservation_entry/stock_reservation_entry.json b/erpnext/stock/doctype/stock_reservation_entry/stock_reservation_entry.json
index 5c3018f..76cedd4 100644
--- a/erpnext/stock/doctype/stock_reservation_entry/stock_reservation_entry.json
+++ b/erpnext/stock/doctype/stock_reservation_entry/stock_reservation_entry.json
@@ -17,8 +17,9 @@
"voucher_no",
"voucher_detail_no",
"column_break_7dxj",
- "against_pick_list",
- "against_pick_list_item",
+ "from_voucher_type",
+ "from_voucher_no",
+ "from_voucher_detail_no",
"section_break_xt4m",
"stock_uom",
"column_break_grdt",
@@ -158,7 +159,7 @@
"oldfieldname": "actual_qty",
"oldfieldtype": "Currency",
"print_width": "150px",
- "read_only_depends_on": "eval: ((doc.reservation_based_on == \"Serial and Batch\") || (doc.against_pick_list) || (doc.delivered_qty > 0))",
+ "read_only_depends_on": "eval: ((doc.reservation_based_on == \"Serial and Batch\") || (doc.from_voucher_type == \"Pick List\") || (doc.delivered_qty > 0))",
"width": "150px"
},
{
@@ -268,27 +269,7 @@
"label": "Reservation Based On",
"no_copy": 1,
"options": "Qty\nSerial and Batch",
- "read_only_depends_on": "eval: (doc.delivered_qty > 0 || doc.against_pick_list)"
- },
- {
- "fieldname": "against_pick_list",
- "fieldtype": "Link",
- "label": "Against Pick List",
- "no_copy": 1,
- "options": "Pick List",
- "print_hide": 1,
- "read_only": 1,
- "report_hide": 1,
- "search_index": 1
- },
- {
- "fieldname": "against_pick_list_item",
- "fieldtype": "Data",
- "label": "Against Pick List Item",
- "no_copy": 1,
- "print_hide": 1,
- "read_only": 1,
- "report_hide": 1
+ "read_only_depends_on": "eval: (doc.delivered_qty > 0 || doc.from_voucher_type == \"Pick List\")"
},
{
"fieldname": "column_break_7dxj",
@@ -297,6 +278,36 @@
{
"fieldname": "column_break_grdt",
"fieldtype": "Column Break"
+ },
+ {
+ "fieldname": "from_voucher_type",
+ "fieldtype": "Select",
+ "label": "From Voucher Type",
+ "no_copy": 1,
+ "options": "\nPick List\nPurchase Receipt",
+ "print_hide": 1,
+ "read_only": 1,
+ "report_hide": 1
+ },
+ {
+ "fieldname": "from_voucher_detail_no",
+ "fieldtype": "Data",
+ "label": "From Voucher Detail No",
+ "no_copy": 1,
+ "print_hide": 1,
+ "read_only": 1,
+ "report_hide": 1
+ },
+ {
+ "fieldname": "from_voucher_no",
+ "fieldtype": "Dynamic Link",
+ "label": "From Voucher No",
+ "no_copy": 1,
+ "options": "from_voucher_type",
+ "print_hide": 1,
+ "read_only": 1,
+ "report_hide": 1,
+ "search_index": 1
}
],
"hide_toolbar": 1,
@@ -304,7 +315,7 @@
"index_web_pages_for_search": 1,
"is_submittable": 1,
"links": [],
- "modified": "2023-08-08 17:15:13.317706",
+ "modified": "2023-10-19 16:41:16.545416",
"modified_by": "Administrator",
"module": "Stock",
"name": "Stock Reservation Entry",
diff --git a/erpnext/stock/doctype/stock_reservation_entry/stock_reservation_entry.py b/erpnext/stock/doctype/stock_reservation_entry/stock_reservation_entry.py
index 936be3f..6b39965 100644
--- a/erpnext/stock/doctype/stock_reservation_entry/stock_reservation_entry.py
+++ b/erpnext/stock/doctype/stock_reservation_entry/stock_reservation_entry.py
@@ -1,6 +1,8 @@
# Copyright (c) 2023, Frappe Technologies Pvt. Ltd. and contributors
# For license information, please see license.txt
+from typing import Literal
+
import frappe
from frappe import _
from frappe.model.document import Document
@@ -113,7 +115,7 @@
"""Auto pick Serial and Batch Nos to reserve when `Reservation Based On` is `Serial and Batch`."""
if (
- not self.against_pick_list
+ not self.from_voucher_type
and (self.get("_action") == "submit")
and (self.has_serial_no or self.has_batch_no)
and cint(frappe.db.get_single_value("Stock Settings", "auto_reserve_serial_and_batch"))
@@ -239,7 +241,7 @@
if available_qty_to_reserve <= 0:
msg = _(
- "Row #{0}: Stock not availabe to reserve for Item {1} against Batch {2} in Warehouse {3}."
+ "Row #{0}: Stock not available to reserve for Item {1} against Batch {2} in Warehouse {3}."
).format(
entry.idx,
frappe.bold(self.item_code),
@@ -316,21 +318,24 @@
) -> None:
"""Updates total reserved qty in the Pick List."""
- if self.against_pick_list and self.against_pick_list_item:
+ if (
+ self.from_voucher_type == "Pick List" and self.from_voucher_no and self.from_voucher_detail_no
+ ):
sre = frappe.qb.DocType("Stock Reservation Entry")
reserved_qty = (
frappe.qb.from_(sre)
.select(Sum(sre.reserved_qty))
.where(
(sre.docstatus == 1)
- & (sre.against_pick_list == self.against_pick_list)
- & (sre.against_pick_list_item == self.against_pick_list_item)
+ & (sre.from_voucher_type == "Pick List")
+ & (sre.from_voucher_no == self.from_voucher_no)
+ & (sre.from_voucher_detail_no == self.from_voucher_detail_no)
)
).run(as_list=True)[0][0] or 0
frappe.db.set_value(
"Pick List Item",
- self.against_pick_list_item,
+ self.from_voucher_detail_no,
reserved_qty_field,
reserved_qty,
update_modified=update_modified,
@@ -365,7 +370,7 @@
).format(self.status, self.doctype)
frappe.throw(msg)
- if self.against_pick_list:
+ if self.from_voucher_type == "Pick List":
msg = _(
"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."
)
@@ -761,25 +766,27 @@
def create_stock_reservation_entries_for_so_items(
- so: object,
+ sales_order: object,
items_details: list[dict] = None,
- against_pick_list: bool = False,
+ from_voucher_type: Literal["Pick List", "Purchase Receipt"] = None,
notify=True,
) -> None:
"""Creates Stock Reservation Entries for Sales Order Items."""
from erpnext.selling.doctype.sales_order.sales_order import get_unreserved_qty
- if not against_pick_list and (
- so.get("_action") == "submit"
- and so.set_warehouse
- and cint(frappe.get_cached_value("Warehouse", so.set_warehouse, "is_group"))
+ if not from_voucher_type and (
+ sales_order.get("_action") == "submit"
+ and sales_order.set_warehouse
+ and cint(frappe.get_cached_value("Warehouse", sales_order.set_warehouse, "is_group"))
):
return frappe.msgprint(
- _("Stock cannot be reserved in the group warehouse {0}.").format(frappe.bold(so.set_warehouse))
+ _("Stock cannot be reserved in the group warehouse {0}.").format(
+ frappe.bold(sales_order.set_warehouse)
+ )
)
- validate_stock_reservation_settings(so)
+ validate_stock_reservation_settings(sales_order)
allow_partial_reservation = frappe.db.get_single_value(
"Stock Settings", "allow_partial_reservation"
@@ -788,38 +795,36 @@
items = []
if items_details:
for item in items_details:
- so_item = frappe.get_doc(
- "Sales Order Item", item.get("sales_order_item") if against_pick_list else item.get("name")
- )
- so_item.reserve_stock = 1
+ so_item = frappe.get_doc("Sales Order Item", item.get("name"))
so_item.warehouse = item.get("warehouse")
so_item.qty_to_reserve = (
- item.get("picked_qty") - item.get("stock_reserved_qty", 0)
- if against_pick_list
- else (flt(item.get("qty_to_reserve")) * flt(so_item.conversion_factor, 1))
+ flt(item.get("qty_to_reserve"))
+ if from_voucher_type in ["Pick List", "Purchase Receipt"]
+ else (
+ flt(item.get("qty_to_reserve"))
+ * (flt(item.get("conversion_factor")) or flt(so_item.conversion_factor) or 1)
+ )
)
-
- if against_pick_list:
- so_item.pick_list = item.get("parent")
- so_item.pick_list_item = item.get("name")
- so_item.pick_list_sbb = item.get("serial_and_batch_bundle")
+ so_item.from_voucher_no = item.get("from_voucher_no")
+ so_item.from_voucher_detail_no = item.get("from_voucher_detail_no")
+ so_item.serial_and_batch_bundle = item.get("serial_and_batch_bundle")
items.append(so_item)
sre_count = 0
- reserved_qty_details = get_sre_reserved_qty_details_for_voucher("Sales Order", so.name)
+ reserved_qty_details = get_sre_reserved_qty_details_for_voucher("Sales Order", sales_order.name)
- for item in items if items_details else so.get("items"):
+ for item in items if items_details else sales_order.get("items"):
# Skip if `Reserved Stock` is not checked for the item.
if not item.get("reserve_stock"):
continue
# Stock should be reserved from the Pick List if has Picked Qty.
- if not against_pick_list and flt(item.picked_qty) > 0:
+ if not from_voucher_type == "Pick List" and flt(item.picked_qty) > 0:
frappe.throw(
- _(
- "Row #{0}: Item {1} has been picked, please create a Stock Reservation from the Pick List."
- ).format(item.idx, frappe.bold(item.item_code))
+ _("Row #{0}: Item {1} has been picked, please reserve stock from the Pick List.").format(
+ item.idx, frappe.bold(item.item_code)
+ )
)
is_stock_item, has_serial_no, has_batch_no = frappe.get_cached_value(
@@ -828,13 +833,15 @@
# Skip if Non-Stock Item.
if not is_stock_item:
- frappe.msgprint(
- _("Row #{0}: Stock cannot be reserved for a non-stock Item {1}").format(
- item.idx, frappe.bold(item.item_code)
- ),
- title=_("Stock Reservation"),
- indicator="yellow",
- )
+ if not from_voucher_type:
+ frappe.msgprint(
+ _("Row #{0}: Stock cannot be reserved for a non-stock Item {1}").format(
+ item.idx, frappe.bold(item.item_code)
+ ),
+ title=_("Stock Reservation"),
+ indicator="yellow",
+ )
+
item.db_set("reserve_stock", 0)
continue
@@ -853,13 +860,15 @@
# Stock is already reserved for the item, notify the user and skip the item.
if unreserved_qty <= 0:
- frappe.msgprint(
- _("Row #{0}: Stock is already reserved for the Item {1}.").format(
- item.idx, frappe.bold(item.item_code)
- ),
- title=_("Stock Reservation"),
- indicator="yellow",
- )
+ if not from_voucher_type:
+ frappe.msgprint(
+ _("Row #{0}: Stock is already reserved for the Item {1}.").format(
+ item.idx, frappe.bold(item.item_code)
+ ),
+ title=_("Stock Reservation"),
+ indicator="yellow",
+ )
+
continue
available_qty_to_reserve = get_available_qty_to_reserve(item.item_code, item.warehouse)
@@ -867,7 +876,7 @@
# No stock available to reserve, notify the user and skip the item.
if available_qty_to_reserve <= 0:
frappe.msgprint(
- _("Row #{0}: No available stock to reserve for the Item {1} in Warehouse {2}.").format(
+ _("Row #{0}: Stock not available to reserve for the Item {1} in Warehouse {2}.").format(
item.idx, frappe.bold(item.item_code), frappe.bold(item.warehouse)
),
title=_("Stock Reservation"),
@@ -893,7 +902,9 @@
# Partial Reservation
if qty_to_be_reserved < unreserved_qty:
- if not item.get("qty_to_reserve") or qty_to_be_reserved < flt(item.get("qty_to_reserve")):
+ if not from_voucher_type and (
+ not item.get("qty_to_reserve") or qty_to_be_reserved < flt(item.get("qty_to_reserve"))
+ ):
msg = _("Row #{0}: Only {1} available to reserve for the Item {2}").format(
item.idx,
frappe.bold(str(qty_to_be_reserved / item.conversion_factor) + " " + item.uom),
@@ -915,33 +926,42 @@
sre.warehouse = item.warehouse
sre.has_serial_no = has_serial_no
sre.has_batch_no = has_batch_no
- sre.voucher_type = so.doctype
- sre.voucher_no = so.name
+ sre.voucher_type = sales_order.doctype
+ sre.voucher_no = sales_order.name
sre.voucher_detail_no = item.name
sre.available_qty = available_qty_to_reserve
sre.voucher_qty = item.stock_qty
sre.reserved_qty = qty_to_be_reserved
- sre.company = so.company
+ sre.company = sales_order.company
sre.stock_uom = item.stock_uom
- sre.project = so.project
+ sre.project = sales_order.project
- if against_pick_list:
- sre.against_pick_list = item.pick_list
- sre.against_pick_list_item = item.pick_list_item
+ if from_voucher_type:
+ sre.from_voucher_type = from_voucher_type
+ sre.from_voucher_no = item.from_voucher_no
+ sre.from_voucher_detail_no = item.from_voucher_detail_no
- if item.pick_list_sbb:
- sbb = frappe.get_doc("Serial and Batch Bundle", item.pick_list_sbb)
- sre.reservation_based_on = "Serial and Batch"
- for entry in sbb.entries:
- sre.append(
- "sb_entries",
- {
- "serial_no": entry.serial_no,
- "batch_no": entry.batch_no,
- "qty": 1 if has_serial_no else abs(entry.qty),
- "warehouse": entry.warehouse,
- },
- )
+ if item.get("serial_and_batch_bundle"):
+ sbb = frappe.get_doc("Serial and Batch Bundle", item.serial_and_batch_bundle)
+ sre.reservation_based_on = "Serial and Batch"
+
+ index, picked_qty = 0, 0
+ while index < len(sbb.entries) and picked_qty < qty_to_be_reserved:
+ entry = sbb.entries[index]
+ qty = 1 if has_serial_no else min(abs(entry.qty), qty_to_be_reserved - picked_qty)
+
+ sre.append(
+ "sb_entries",
+ {
+ "serial_no": entry.serial_no,
+ "batch_no": entry.batch_no,
+ "qty": qty,
+ "warehouse": entry.warehouse,
+ },
+ )
+
+ index += 1
+ picked_qty += qty
sre.save()
sre.submit()
@@ -956,29 +976,37 @@
voucher_type: str = None,
voucher_no: str = None,
voucher_detail_no: str = None,
- against_pick_list: str = None,
+ from_voucher_type: Literal["Pick List", "Purchase Receipt"] = None,
+ from_voucher_no: str = None,
+ from_voucher_detail_no: str = None,
sre_list: list[dict] = None,
notify: bool = True,
) -> None:
"""Cancel Stock Reservation Entries."""
- if not sre_list and against_pick_list:
- sre = frappe.qb.DocType("Stock Reservation Entry")
- sre_list = (
- frappe.qb.from_(sre)
- .select(sre.name)
- .where(
- (sre.docstatus == 1)
- & (sre.against_pick_list == against_pick_list)
- & (sre.status.notin(["Delivered", "Cancelled"]))
+ if not sre_list:
+ if voucher_type and voucher_no:
+ sre_list = get_stock_reservation_entries_for_voucher(
+ voucher_type, voucher_no, voucher_detail_no, fields=["name"]
)
- .orderby(sre.creation)
- ).run(as_dict=True)
+ elif from_voucher_type and from_voucher_no:
+ sre = frappe.qb.DocType("Stock Reservation Entry")
+ query = (
+ frappe.qb.from_(sre)
+ .select(sre.name)
+ .where(
+ (sre.docstatus == 1)
+ & (sre.from_voucher_type == from_voucher_type)
+ & (sre.from_voucher_no == from_voucher_no)
+ & (sre.status.notin(["Delivered", "Cancelled"]))
+ )
+ .orderby(sre.creation)
+ )
- elif not sre_list and (voucher_type and voucher_no):
- sre_list = get_stock_reservation_entries_for_voucher(
- voucher_type, voucher_no, voucher_detail_no, fields=["name"]
- )
+ if from_voucher_detail_no:
+ query = query.where(sre.from_voucher_detail_no == from_voucher_detail_no)
+
+ sre_list = query.run(as_dict=True)
if sre_list:
for sre in sre_list:
diff --git a/erpnext/stock/doctype/stock_reservation_entry/test_stock_reservation_entry.py b/erpnext/stock/doctype/stock_reservation_entry/test_stock_reservation_entry.py
index 1168a4e..f4c74a8 100644
--- a/erpnext/stock/doctype/stock_reservation_entry/test_stock_reservation_entry.py
+++ b/erpnext/stock/doctype/stock_reservation_entry/test_stock_reservation_entry.py
@@ -5,6 +5,7 @@
import frappe
from frappe.tests.utils import FrappeTestCase, change_settings
+from frappe.utils import today
from erpnext.selling.doctype.sales_order.sales_order import create_pick_list, make_delivery_note
from erpnext.selling.doctype.sales_order.test_sales_order import make_sales_order
@@ -28,10 +29,6 @@
items={self.sr_item.name: self.sr_item}, warehouse=self.warehouse, qty=100
)
- def tearDown(self) -> None:
- cancel_all_stock_reservation_entries()
- return super().tearDown()
-
@change_settings("Stock Settings", {"allow_negative_stock": 0})
def test_validate_stock_reservation_settings(self) -> None:
from erpnext.stock.doctype.stock_reservation_entry.stock_reservation_entry import (
@@ -555,8 +552,9 @@
(sre.voucher_type == "Sales Order")
& (sre.voucher_no == location.sales_order)
& (sre.voucher_detail_no == location.sales_order_item)
- & (sre.against_pick_list == pl.name)
- & (sre.against_pick_list_item == location.name)
+ & (sre.from_voucher_type == "Pick List")
+ & (sre.from_voucher_no == pl.name)
+ & (sre.from_voucher_detail_no == location.name)
)
).run(as_dict=True)
reserved_sb_details: set[tuple] = {
@@ -567,6 +565,90 @@
# Test - 3: Reserved Serial/Batch Nos should be equal to Picked Serial/Batch Nos.
self.assertSetEqual(picked_sb_details, reserved_sb_details)
+ @change_settings(
+ "Stock Settings",
+ {
+ "allow_negative_stock": 0,
+ "enable_stock_reservation": 1,
+ "auto_reserve_serial_and_batch": 1,
+ "pick_serial_and_batch_based_on": "FIFO",
+ "auto_reserve_stock_for_sales_order_on_purchase": 1,
+ },
+ )
+ def test_stock_reservation_from_purchase_receipt(self):
+ from erpnext.buying.doctype.purchase_order.purchase_order import make_purchase_receipt
+ from erpnext.selling.doctype.sales_order.sales_order import make_material_request
+ from erpnext.stock.doctype.material_request.material_request import make_purchase_order
+
+ items_details = create_items()
+ create_material_receipt(items_details, self.warehouse, qty=10)
+
+ item_list = []
+ for item_code, properties in items_details.items():
+ item_list.append(
+ {
+ "item_code": item_code,
+ "warehouse": self.warehouse,
+ "qty": randint(11, 100),
+ "uom": properties.stock_uom,
+ "rate": randint(10, 400),
+ }
+ )
+
+ so = make_sales_order(
+ item_list=item_list,
+ warehouse=self.warehouse,
+ )
+
+ mr = make_material_request(so.name)
+ mr.schedule_date = today()
+ mr.save().submit()
+
+ po = make_purchase_order(mr.name)
+ po.supplier = "_Test Supplier"
+ po.save().submit()
+
+ pr = make_purchase_receipt(po.name)
+ pr.save().submit()
+
+ for item in pr.items:
+ sre, status, reserved_qty = frappe.db.get_value(
+ "Stock Reservation Entry",
+ {
+ "from_voucher_type": "Purchase Receipt",
+ "from_voucher_no": pr.name,
+ "from_voucher_detail_no": item.name,
+ },
+ ["name", "status", "reserved_qty"],
+ )
+
+ # Test - 1: SRE status should be `Reserved`.
+ self.assertEqual(status, "Reserved")
+
+ # Test - 2: SRE Reserved Qty should be equal to PR Item Qty.
+ self.assertEqual(reserved_qty, item.qty)
+
+ if item.serial_and_batch_bundle:
+ sb_details = frappe.db.get_all(
+ "Serial and Batch Entry",
+ filters={"parent": item.serial_and_batch_bundle},
+ fields=["serial_no", "batch_no", "qty"],
+ as_list=True,
+ )
+ reserved_sb_details = frappe.db.get_all(
+ "Serial and Batch Entry",
+ filters={"parent": sre},
+ fields=["serial_no", "batch_no", "qty"],
+ as_list=True,
+ )
+
+ # Test - 3: Reserved Serial/Batch Nos should be equal to PR Item Serial/Batch Nos.
+ self.assertEqual(set(sb_details), set(reserved_sb_details))
+
+ def tearDown(self) -> None:
+ cancel_all_stock_reservation_entries()
+ return super().tearDown()
+
def create_items() -> dict:
items_properties = [
diff --git a/erpnext/stock/doctype/stock_settings/stock_settings.json b/erpnext/stock/doctype/stock_settings/stock_settings.json
index 2052daa..1228290 100644
--- a/erpnext/stock/doctype/stock_settings/stock_settings.json
+++ b/erpnext/stock/doctype/stock_settings/stock_settings.json
@@ -38,8 +38,8 @@
"stock_reservation_tab",
"enable_stock_reservation",
"column_break_rx3e",
- "auto_reserve_stock_for_sales_order",
"allow_partial_reservation",
+ "auto_reserve_stock_for_sales_order_on_purchase",
"serial_and_batch_reservation_section",
"auto_reserve_serial_and_batch",
"serial_and_batch_item_settings_tab",
@@ -65,8 +65,7 @@
"stock_frozen_upto_days",
"column_break_26",
"role_allowed_to_create_edit_back_dated_transactions",
- "stock_auth_role",
- "section_break_plhx"
+ "stock_auth_role"
],
"fields": [
{
@@ -356,7 +355,7 @@
{
"default": "1",
"depends_on": "eval: doc.enable_stock_reservation",
- "description": "If enabled, <b>Partial Stock Reservation Entries</b> can be created. For example, If you have a Sales Order of 100 units and the Available Stock is 90 units then a Stock Reservation Entry will be created for 90 units. ",
+ "description": "Partial stock can be reserved. For example, If you have a Sales Order of 100 units and the Available Stock is 90 units then a Stock Reservation Entry will be created for 90 units. ",
"fieldname": "allow_partial_reservation",
"fieldtype": "Check",
"label": "Allow Partial Reservation"
@@ -383,7 +382,7 @@
{
"default": "1",
"depends_on": "eval: doc.enable_stock_reservation",
- "description": "If enabled, Serial and Batch Nos will be auto-reserved based on <b>Pick Serial / Batch Based On</b>",
+ "description": "Serial and Batch Nos will be auto-reserved based on <b>Pick Serial / Batch Based On</b>",
"fieldname": "auto_reserve_serial_and_batch",
"fieldtype": "Check",
"label": "Auto Reserve Serial and Batch Nos"
@@ -394,14 +393,6 @@
"label": "Serial and Batch Reservation"
},
{
- "default": "0",
- "depends_on": "eval: doc.enable_stock_reservation",
- "description": "If enabled, <b>Stock Reservation Entries</b> will be created on submission of <b>Sales Order</b>",
- "fieldname": "auto_reserve_stock_for_sales_order",
- "fieldtype": "Check",
- "label": "Auto Reserve Stock for Sales Order"
- },
- {
"fieldname": "conversion_factor_section",
"fieldtype": "Section Break",
"label": "Stock UOM Quantity"
@@ -421,6 +412,14 @@
"fieldname": "allow_to_edit_stock_uom_qty_for_purchase",
"fieldtype": "Check",
"label": "Allow to Edit Stock UOM Qty for Purchase Documents"
+ },
+ {
+ "default": "0",
+ "depends_on": "eval: doc.enable_stock_reservation",
+ "description": "Stock will be reserved on submission of <b>Purchase Receipt</b> created against Material Receipt for Sales Order.",
+ "fieldname": "auto_reserve_stock_for_sales_order_on_purchase",
+ "fieldtype": "Check",
+ "label": "Auto Reserve Stock for Sales Order on Purchase"
}
],
"icon": "icon-cog",
@@ -428,7 +427,7 @@
"index_web_pages_for_search": 1,
"issingle": 1,
"links": [],
- "modified": "2023-10-01 14:22:36.136111",
+ "modified": "2023-10-18 12:35:30.068799",
"modified_by": "Administrator",
"module": "Stock",
"name": "Stock Settings",
@@ -453,4 +452,4 @@
"sort_order": "ASC",
"states": [],
"track_changes": 1
-}
+}
\ No newline at end of file
diff --git a/erpnext/stock/get_item_details.py b/erpnext/stock/get_item_details.py
index 8c6fd84..e29fc88 100644
--- a/erpnext/stock/get_item_details.py
+++ b/erpnext/stock/get_item_details.py
@@ -268,7 +268,7 @@
if not item:
item = frappe.get_doc("Item", args.get("item_code"))
- if item.variant_of:
+ if item.variant_of and not item.taxes:
item.update_template_tables()
item_defaults = get_item_defaults(item.name, args.company)
@@ -330,8 +330,12 @@
),
"expense_account": expense_account
or get_default_expense_account(args, item_defaults, item_group_defaults, brand_defaults),
- "discount_account": get_default_discount_account(args, item_defaults),
- "provisional_expense_account": get_provisional_account(args, item_defaults),
+ "discount_account": get_default_discount_account(
+ args, item_defaults, item_group_defaults, brand_defaults
+ ),
+ "provisional_expense_account": get_provisional_account(
+ args, item_defaults, item_group_defaults, brand_defaults
+ ),
"cost_center": get_default_cost_center(
args, item_defaults, item_group_defaults, brand_defaults
),
@@ -686,12 +690,22 @@
)
-def get_provisional_account(args, item):
- return item.get("default_provisional_account") or args.default_provisional_account
+def get_provisional_account(args, item, item_group, brand):
+ return (
+ item.get("default_provisional_account")
+ or item_group.get("default_provisional_account")
+ or brand.get("default_provisional_account")
+ or args.default_provisional_account
+ )
-def get_default_discount_account(args, item):
- return item.get("default_discount_account") or args.discount_account
+def get_default_discount_account(args, item, item_group, brand):
+ return (
+ item.get("default_discount_account")
+ or item_group.get("default_discount_account")
+ or brand.get("default_discount_account")
+ or args.discount_account
+ )
def get_default_deferred_account(args, item, fieldname=None):
diff --git a/erpnext/stock/report/reserved_stock/reserved_stock.js b/erpnext/stock/report/reserved_stock/reserved_stock.js
index 2199f52..6872741 100644
--- a/erpnext/stock/report/reserved_stock/reserved_stock.js
+++ b/erpnext/stock/report/reserved_stock/reserved_stock.js
@@ -91,16 +91,30 @@
},
},
{
- fieldname: "against_pick_list",
- label: __("Against Pick List"),
+ fieldname: "from_voucher_type",
+ label: __("From Voucher Type"),
fieldtype: "Link",
- options: "Pick List",
+ options: "DocType",
+ get_query: () => ({
+ filters: {
+ name: ["in", ["Pick List", "Purchase Receipt"]],
+ }
+ }),
+ },
+ {
+ fieldname: "from_voucher_no",
+ label: __("From Voucher No"),
+ fieldtype: "Dynamic Link",
+ options: "from_voucher_type",
get_query: () => ({
filters: {
docstatus: 1,
company: frappe.query_report.get_filter_value("company"),
},
}),
+ get_options: function () {
+ return frappe.query_report.get_filter_value("from_voucher_type");
+ },
},
{
fieldname: "reservation_based_on",
diff --git a/erpnext/stock/report/reserved_stock/reserved_stock.py b/erpnext/stock/report/reserved_stock/reserved_stock.py
index d93ee1c..21ce203 100644
--- a/erpnext/stock/report/reserved_stock/reserved_stock.py
+++ b/erpnext/stock/report/reserved_stock/reserved_stock.py
@@ -44,7 +44,8 @@
(sre.available_qty - sre.reserved_qty).as_("available_qty"),
sre.voucher_type,
sre.voucher_no,
- sre.against_pick_list,
+ sre.from_voucher_type,
+ sre.from_voucher_no,
sre.name.as_("stock_reservation_entry"),
sre.status,
sre.project,
@@ -65,7 +66,8 @@
"warehouse",
"voucher_type",
"voucher_no",
- "against_pick_list",
+ "from_voucher_type",
+ "from_voucher_no",
"reservation_based_on",
"status",
"project",
@@ -142,7 +144,6 @@
"fieldname": "voucher_type",
"label": _("Voucher Type"),
"fieldtype": "Data",
- "options": "Warehouse",
"width": 110,
},
{
@@ -153,11 +154,17 @@
"width": 120,
},
{
- "fieldname": "against_pick_list",
- "label": _("Against Pick List"),
- "fieldtype": "Link",
- "options": "Pick List",
- "width": 130,
+ "fieldname": "from_voucher_type",
+ "label": _("From Voucher Type"),
+ "fieldtype": "Data",
+ "width": 110,
+ },
+ {
+ "fieldname": "from_voucher_no",
+ "label": _("From Voucher No"),
+ "fieldtype": "Dynamic Link",
+ "options": "from_voucher_type",
+ "width": 120,
},
{
"fieldname": "stock_reservation_entry",
diff --git a/erpnext/subcontracting/doctype/subcontracting_order/subcontracting_order.js b/erpnext/subcontracting/doctype/subcontracting_order/subcontracting_order.js
index f2b395a..587a3b4 100644
--- a/erpnext/subcontracting/doctype/subcontracting_order/subcontracting_order.js
+++ b/erpnext/subcontracting/doctype/subcontracting_order/subcontracting_order.js
@@ -107,7 +107,7 @@
get_materials_from_supplier: function (frm) {
let sco_rm_details = [];
- if (frm.doc.status != "Closed" && frm.doc.supplied_items && frm.doc.per_received > 0) {
+ if (frm.doc.status != "Closed" && frm.doc.supplied_items) {
frm.doc.supplied_items.forEach(d => {
if (d.total_supplied_qty > 0 && d.total_supplied_qty != d.consumed_qty) {
sco_rm_details.push(d.name);
@@ -193,7 +193,7 @@
}
has_unsupplied_items() {
- return this.frm.doc['supplied_items'].some(item => item.required_qty > item.supplied_qty);
+ return this.frm.doc['supplied_items'].some(item => item.required_qty > (item.supplied_qty - item.returned_qty));
}
make_subcontracting_receipt() {
diff --git a/erpnext/subcontracting/doctype/subcontracting_receipt/subcontracting_receipt.py b/erpnext/subcontracting/doctype/subcontracting_receipt/subcontracting_receipt.py
index 6aecaf9..7e06444 100644
--- a/erpnext/subcontracting/doctype/subcontracting_receipt/subcontracting_receipt.py
+++ b/erpnext/subcontracting/doctype/subcontracting_receipt/subcontracting_receipt.py
@@ -410,7 +410,6 @@
def make_item_gl_entries(self, gl_entries, warehouse_account=None):
stock_rbnb = self.get_company_default("stock_received_but_not_billed")
- expenses_included_in_valuation = self.get_company_default("expenses_included_in_valuation")
warehouse_with_no_account = []
@@ -482,10 +481,7 @@
divisional_loss = flt(item.amount - stock_value_diff, item.precision("amount"))
if divisional_loss:
- if self.is_return:
- loss_account = expenses_included_in_valuation
- else:
- loss_account = item.expense_account
+ loss_account = item.expense_account
self.add_gl_entry(
gl_entries=gl_entries,
diff --git a/erpnext/support/doctype/issue/issue.js b/erpnext/support/doctype/issue/issue.js
index d4daacd..f96823b 100644
--- a/erpnext/support/doctype/issue/issue.js
+++ b/erpnext/support/doctype/issue/issue.js
@@ -1,13 +1,6 @@
frappe.ui.form.on("Issue", {
onload: function(frm) {
frm.email_field = "raised_by";
- frm.set_query("customer", function () {
- return {
- filters: {
- "disabled": 0
- }
- };
- });
frappe.db.get_value("Support Settings", {name: "Support Settings"},
["allow_resetting_service_level_agreement", "track_service_level_agreement"], (r) => {
diff --git a/erpnext/templates/pages/projects.html b/erpnext/templates/pages/projects.html
index 9fe4338..3b8698f 100644
--- a/erpnext/templates/pages/projects.html
+++ b/erpnext/templates/pages/projects.html
@@ -14,18 +14,16 @@
{% block style %}
<style>
- {
- % include "templates/includes/projects.css"%
- }
+ {% include "templates/includes/projects.css" %}
</style>
{% endblock %}
{% block page_content %}
<div class="web-list-item transaction-list-item">
<div class="row align-items-center">
- <div class="col-sm-4 "><b>Status: {{ doc.status }}</b></div>
- <div class="col-sm-4 "><b>Progress: {{ doc.percent_complete }}%</b></div>
- <div class="col-sm-4 "><b>Hours Spent: {{ doc.actual_time | round }}</b></div>
+ <div class="col-sm-4 "><b>{{ _("Status") }}: {{ _(doc.status) }}</b></div>
+ <div class="col-sm-4 "><b>{{ _("Progress") }}: {{ doc.get_formatted("percent_complete") }}</b></div>
+ <div class="col-sm-4 "><b>{{ _("Hours Spent") }}: {{ doc.get_formatted("actual_time") }}</b></div>
</div>
</div>
@@ -34,7 +32,7 @@
<hr>
<div class="row align-items-center">
- <div class="col-sm-6 my-account-header"> <h4>Tasks</h4></div>
+ <div class="col-sm-6 my-account-header"> <h4>{{ _("Tasks") }}</h4></div>
<div class="col-sm-6 text-right">
<a class="btn btn-secondary btn-light btn-sm" href='/tasks/new?project={{ doc.project_name }}'>{{ _("New task") }}</a>
</div>
@@ -44,39 +42,39 @@
<div class="result">
<div class="web-list-item transaction-list-item">
<div class="row align-items-center">
- <div class="col-sm-4"><b>Tasks</b></div>
- <div class="col-sm-2"><b>Status</b></div>
- <div class="col-sm-2"><b>End Date</b></div>
- <div class="col-sm-2"><b>Assignment</b></div>
- <div class="col-sm-2"><b>Modified On</b></div>
+ <div class="col-sm-4"><b>{{ _("Tasks") }}</b></div>
+ <div class="col-sm-2"><b>{{ _("Status") }}</b></div>
+ <div class="col-sm-2"><b>{{ _("End Date") }}</b></div>
+ <div class="col-sm-2"><b>{{ _("Assignment") }}</b></div>
+ <div class="col-sm-2"><b>{{ _("Modified On") }}</b></div>
</div>
</div>
{% include "erpnext/templates/includes/projects/project_tasks.html" %}
</div>
</div>
{% else %}
- {{ empty_state('Task')}}
+ {{ empty_state(_("Task")) }}
{% endif %}
- <h4 class="my-account-header">Timesheets</h4>
+ <h4 class="my-account-header">{{ _("Timesheets") }}</h4>
{% if doc.timesheets %}
<div class="website-list">
<div class="result">
<div class="web-list-item transaction-list-item">
<div class="row align-items-center">
- <div class="col-xs-2"><b>Timesheet</b></div>
- <div class="col-xs-2"><b>Status</b></div>
- <div class="col-xs-2"><b>From</b></div>
- <div class="col-xs-2"><b>To</b></div>
- <div class="col-xs-2"><b>Modified By</b></div>
- <div class="col-xs-2"><b>Modified On</b></div>
+ <div class="col-xs-2"><b>{{ _("Timesheet") }}</b></div>
+ <div class="col-xs-2"><b>{{ _("Status") }}</b></div>
+ <div class="col-xs-2"><b>{{ _("From") }}</b></div>
+ <div class="col-xs-2"><b>{{ _("To") }}</b></div>
+ <div class="col-xs-2"><b>{{ _("Modified By") }}</b></div>
+ <div class="col-xs-2"><b>{{ _("Modified On") }}</b></div>
</div>
</div>
{% include "erpnext/templates/includes/projects/project_timesheets.html" %}
</div>
</div>
{% else %}
- {{ empty_state('Timesheet')}}
+ {{ empty_state(_("Timesheet")) }}
{% endif %}
{% if doc.attachments %}
@@ -113,7 +111,7 @@
{% macro progress_bar(percent_complete) %}
{% if percent_complete %}
- <span class="small py-2">Project Progress:</span>
+ <span class="small py-2">{{ _("Project Progress:") }}</span>
<div class="progress progress-hg" style="height: 15px;">
<div
class="progress-bar progress-bar-{{ 'warning' if percent_complete|round < 100 else 'success' }} active"\
@@ -133,7 +131,7 @@
<div>
<img src="/assets/frappe/images/ui-states/list-empty-state.svg" alt="Generic Empty State" class="null-state">
</div>
- <p>You haven't created a {{ section_name }} yet</p>
+ <p>{{ _("You haven't created a {0} yet").format(section_name) }}</p>
</div>
</div>
</div>
diff --git a/erpnext/translations/af.csv b/erpnext/translations/af.csv
index d4b823d..f457314 100644
--- a/erpnext/translations/af.csv
+++ b/erpnext/translations/af.csv
@@ -7052,7 +7052,7 @@
Warranty Period (in days),Garantie Periode (in dae),
Auto re-order,Outo herbestel,
Reorder level based on Warehouse,Herbestel vlak gebaseer op Warehouse,
-Will also apply for variants unless overrridden,Sal ook aansoek doen vir variante tensy dit oortree word,
+Will also apply for variants unless overridden,Sal ook aansoek doen vir variante tensy dit oortree word,
Units of Measure,Eenhede van maatreël,
Will also apply for variants,Sal ook aansoek doen vir variante,
Serial Nos and Batches,Serial Nos and Batches,
diff --git a/erpnext/translations/am.csv b/erpnext/translations/am.csv
index 764868d..0453d5d 100644
--- a/erpnext/translations/am.csv
+++ b/erpnext/translations/am.csv
@@ -7052,7 +7052,7 @@
Warranty Period (in days),(ቀናት ውስጥ) የዋስትና ክፍለ ጊዜ,
Auto re-order,ራስ-ዳግም-ትዕዛዝ,
Reorder level based on Warehouse,መጋዘን ላይ የተመሠረተ አስይዝ ደረጃ,
-Will also apply for variants unless overrridden,overrridden በስተቀር ደግሞ ተለዋጮች ማመልከት ይሆን,
+Will also apply for variants unless overridden,overridden በስተቀር ደግሞ ተለዋጮች ማመልከት ይሆን,
Units of Measure,ይለኩ አሃዶች,
Will also apply for variants,በተጨማሪም ተለዋጮች ማመልከት ይሆን,
Serial Nos and Batches,ተከታታይ ቁጥሮች እና ቡድኖች,
diff --git a/erpnext/translations/ar.csv b/erpnext/translations/ar.csv
index 4e03a18..67b409e 100644
--- a/erpnext/translations/ar.csv
+++ b/erpnext/translations/ar.csv
@@ -7052,7 +7052,7 @@
Warranty Period (in days),فترة الضمان (بالأيام),
Auto re-order,إعادة ترتيب تلقائي,
Reorder level based on Warehouse,مستوى إعادة الطلب بناء على مستودع,
-Will also apply for variants unless overrridden,سوف تطبق أيضا على المتغيرات الا اذا تم التغير فوقها,
+Will also apply for variants unless overridden,سوف تطبق أيضا على المتغيرات الا اذا تم التغير فوقها,
Units of Measure,وحدات القياس,
Will also apply for variants,سوف تطبق أيضا على المتغيرات,
Serial Nos and Batches,الرقم التسلسلي ودفعات,
diff --git a/erpnext/translations/bg.csv b/erpnext/translations/bg.csv
index 8dff755..787f81e 100644
--- a/erpnext/translations/bg.csv
+++ b/erpnext/translations/bg.csv
@@ -7052,7 +7052,7 @@
Warranty Period (in days),Гаранционен срок (в дни),
Auto re-order,Автоматична повторна поръчка,
Reorder level based on Warehouse,Пренареждане равнище въз основа на Warehouse,
-Will also apply for variants unless overrridden,"Ще се прилага и за варианти, освен ако overrridden",
+Will also apply for variants unless overridden,"Ще се прилага и за варианти, освен ако overridden",
Units of Measure,Мерни единици за измерване,
Will also apply for variants,Ще се прилага и за варианти,
Serial Nos and Batches,Серийни номера и партиди,
diff --git a/erpnext/translations/bn.csv b/erpnext/translations/bn.csv
index 8a698df..69fd08c 100644
--- a/erpnext/translations/bn.csv
+++ b/erpnext/translations/bn.csv
@@ -7052,7 +7052,7 @@
Warranty Period (in days),(দিন) ওয়্যারেন্টি সময়কাল,
Auto re-order,অটো পুনরায় আদেশ,
Reorder level based on Warehouse,গুদাম উপর ভিত্তি রেকর্ডার স্তর,
-Will also apply for variants unless overrridden,Overrridden তবে এছাড়াও ভিন্নতা জন্য আবেদন করতে হবে,
+Will also apply for variants unless overridden,Overrridden তবে এছাড়াও ভিন্নতা জন্য আবেদন করতে হবে,
Units of Measure,পরিমাপ ইউনিট,
Will also apply for variants,এছাড়াও ভিন্নতা জন্য আবেদন করতে হবে,
Serial Nos and Batches,সিরিয়াল আমরা এবং ব্যাচ,
diff --git a/erpnext/translations/bs.csv b/erpnext/translations/bs.csv
index 7ba4a88..ef680a3 100644
--- a/erpnext/translations/bs.csv
+++ b/erpnext/translations/bs.csv
@@ -7052,7 +7052,7 @@
Warranty Period (in days),Jamstveni period (u danima),
Auto re-order,Autorefiniš reda,
Reorder level based on Warehouse,Nivo Ponovno red zasnovan na Skladište,
-Will also apply for variants unless overrridden,Primjenjivat će se i za varijante osim overrridden,
+Will also apply for variants unless overridden,Primjenjivat će se i za varijante osim overridden,
Units of Measure,Jedinice mjere,
Will also apply for variants,Primjenjivat će se i za varijante,
Serial Nos and Batches,Serijski brojevi i Paketi,
diff --git a/erpnext/translations/ca.csv b/erpnext/translations/ca.csv
index cce1f3a..fa545a4 100644
--- a/erpnext/translations/ca.csv
+++ b/erpnext/translations/ca.csv
@@ -7052,7 +7052,7 @@
Warranty Period (in days),Període de garantia (en dies),
Auto re-order,Acte reordenar,
Reorder level based on Warehouse,Nivell de comanda basat en Magatzem,
-Will also apply for variants unless overrridden,També s'aplicarà per a les variants menys overrridden,
+Will also apply for variants unless overridden,També s'aplicarà per a les variants menys overridden,
Units of Measure,Unitats de mesura,
Will also apply for variants,També s'aplicarà per a les variants,
Serial Nos and Batches,Nº de sèrie i lots,
diff --git a/erpnext/translations/cs.csv b/erpnext/translations/cs.csv
index 1072ed3..7fb1679 100644
--- a/erpnext/translations/cs.csv
+++ b/erpnext/translations/cs.csv
@@ -7052,7 +7052,7 @@
Warranty Period (in days),Záruční doba (ve dnech),
Auto re-order,Automatické znovuobjednání,
Reorder level based on Warehouse,Úroveň Změna pořadí na základě Warehouse,
-Will also apply for variants unless overrridden,"Bude platit i pro varianty, pokud nebude přepsáno",
+Will also apply for variants unless overridden,"Bude platit i pro varianty, pokud nebude přepsáno",
Units of Measure,Jednotky měření,
Will also apply for variants,Bude platit i pro varianty,
Serial Nos and Batches,Sériové čísla a dávky,
diff --git a/erpnext/translations/cz.csv b/erpnext/translations/cz.csv
index 270a710..96de062 100644
--- a/erpnext/translations/cz.csv
+++ b/erpnext/translations/cz.csv
@@ -1991,7 +1991,7 @@
Actual End Date,Skutečné datum ukončen$1,
Applicable To (Role),Vztahující se na (Role)
Purpose,Účel,
-Will also apply for variants unless overrridden,"Bude platit i pro varianty, pokud nebude přepsáno"
+Will also apply for variants unless overridden,"Bude platit i pro varianty, pokud nebude přepsáno"
Advances,Zálohy,
Approving User cannot be same as user the rule is Applicable To,Schválení Uživatel nemůže být stejná jako uživatel pravidlo se vztahuje na,
No of Requested SMS,Počet žádaným SMS,
diff --git a/erpnext/translations/da.csv b/erpnext/translations/da.csv
index 138da5d..4eb3960 100644
--- a/erpnext/translations/da.csv
+++ b/erpnext/translations/da.csv
@@ -7052,7 +7052,7 @@
Warranty Period (in days),Garantiperiode (i dage),
Auto re-order,Auto genbestil,
Reorder level based on Warehouse,Genbestil niveau baseret på Warehouse,
-Will also apply for variants unless overrridden,"Vil også gælde for varianter, medmindre overrridden",
+Will also apply for variants unless overridden,"Vil også gælde for varianter, medmindre overridden",
Units of Measure,Måleenheder,
Will also apply for variants,Vil også gælde for varianter,
Serial Nos and Batches,Serienummer og partier,
diff --git a/erpnext/translations/de.csv b/erpnext/translations/de.csv
index 9a4137c..c627f81 100644
--- a/erpnext/translations/de.csv
+++ b/erpnext/translations/de.csv
@@ -7074,7 +7074,7 @@
Warranty Period (in days),Garantiefrist (in Tagen),
Auto re-order,Automatische Nachbestellung,
Reorder level based on Warehouse,Meldebestand auf Basis des Lagers,
-Will also apply for variants unless overrridden,"Gilt auch für Varianten, sofern nicht außer Kraft gesetzt",
+Will also apply for variants unless overridden,"Gilt auch für Varianten, sofern nicht außer Kraft gesetzt",
Units of Measure,Maßeinheiten,
Will also apply for variants,Gilt auch für Varianten,
Serial Nos and Batches,Seriennummern und Chargen,
diff --git a/erpnext/translations/el.csv b/erpnext/translations/el.csv
index 7a83cc5..21fb435 100644
--- a/erpnext/translations/el.csv
+++ b/erpnext/translations/el.csv
@@ -7052,7 +7052,7 @@
Warranty Period (in days),Περίοδος εγγύησης (σε ημέρες),
Auto re-order,Αυτόματη εκ νέου προκειμένου,
Reorder level based on Warehouse,Αναδιάταξη επίπεδο με βάση Αποθήκης,
-Will also apply for variants unless overrridden,Θα ισχύουν επίσης για τις παραλλαγές εκτός αν υπάρχει υπέρβαση,
+Will also apply for variants unless overridden,Θα ισχύουν επίσης για τις παραλλαγές εκτός αν υπάρχει υπέρβαση,
Units of Measure,Μονάδες μέτρησης,
Will also apply for variants,Θα ισχύουν επίσης για τις παραλλαγές,
Serial Nos and Batches,Σειριακοί αριθμοί και παρτίδες,
diff --git a/erpnext/translations/es.csv b/erpnext/translations/es.csv
index fadf7a7..2abe418 100644
--- a/erpnext/translations/es.csv
+++ b/erpnext/translations/es.csv
@@ -7052,7 +7052,7 @@
Warranty Period (in days),Período de garantía (en días),
Auto re-order,Ordenar Automáticamente,
Reorder level based on Warehouse,Nivel de reabastecimiento basado en almacén,
-Will also apply for variants unless overrridden,También se aplicará para las variantes menos que se sobre escriba,
+Will also apply for variants unless overridden,También se aplicará para las variantes menos que se sobre escriba,
Units of Measure,Unidades de medida,
Will also apply for variants,También se aplicará para las variantes,
Serial Nos and Batches,Números de serie y lotes,
diff --git a/erpnext/translations/et.csv b/erpnext/translations/et.csv
index 4e26a82..a4a8736 100644
--- a/erpnext/translations/et.csv
+++ b/erpnext/translations/et.csv
@@ -7052,7 +7052,7 @@
Warranty Period (in days),Garantii Periood (päeva),
Auto re-order,Auto ümber korraldada,
Reorder level based on Warehouse,Reorder tasandil põhineb Warehouse,
-Will also apply for variants unless overrridden,"Kehtib ka variante, kui overrridden",
+Will also apply for variants unless overridden,"Kehtib ka variante, kui overridden",
Units of Measure,Mõõtühikud,
Will also apply for variants,Kehtib ka variandid,
Serial Nos and Batches,Serial Nos ning partiid,
diff --git a/erpnext/translations/fa.csv b/erpnext/translations/fa.csv
index 530965d..bd40c8b 100644
--- a/erpnext/translations/fa.csv
+++ b/erpnext/translations/fa.csv
@@ -7052,7 +7052,7 @@
Warranty Period (in days),دوره گارانتی (در روز),
Auto re-order,خودکار دوباره سفارش,
Reorder level based on Warehouse,سطح تغییر مجدد ترتیب بر اساس انبار,
-Will also apply for variants unless overrridden,همچنین برای انواع اعمال می شود مگر اینکه overrridden,
+Will also apply for variants unless overridden,همچنین برای انواع اعمال می شود مگر اینکه overridden,
Units of Measure,واحدهای اندازه گیری,
Will also apply for variants,همچنین برای انواع اعمال می شود,
Serial Nos and Batches,سریال شماره و دسته,
diff --git a/erpnext/translations/fi.csv b/erpnext/translations/fi.csv
index 6e9380c..33cf157 100644
--- a/erpnext/translations/fi.csv
+++ b/erpnext/translations/fi.csv
@@ -7052,7 +7052,7 @@
Warranty Period (in days),Takuuaika (päivinä),
Auto re-order,Auto re-order,
Reorder level based on Warehouse,Varastoon perustuva täydennystilaustaso,
-Will also apply for variants unless overrridden,"Sovelletaan myös tuotemalleissa, ellei kumota",
+Will also apply for variants unless overridden,"Sovelletaan myös tuotemalleissa, ellei kumota",
Units of Measure,Mittayksiköt,
Will also apply for variants,Sovelletaan myös tuotemalleissa,
Serial Nos and Batches,Sarjanumerot ja Erät,
diff --git a/erpnext/translations/fr.csv b/erpnext/translations/fr.csv
index d3875c1..d15af74 100644
--- a/erpnext/translations/fr.csv
+++ b/erpnext/translations/fr.csv
@@ -6650,7 +6650,7 @@
Warranty Period (in days),Période de Garantie (en jours),
Auto re-order,Re-commande auto,
Reorder level based on Warehouse,Niveau de réapprovisionnement basé sur l’Entrepôt,
-Will also apply for variants unless overrridden,S'appliquera également pour des variantes sauf si remplacé,
+Will also apply for variants unless overridden,S'appliquera également pour des variantes sauf si remplacé,
Units of Measure,Unités de Mesure,
Will also apply for variants,S'appliquera également pour les variantes,
Serial Nos and Batches,N° de Série et Lots,
diff --git a/erpnext/translations/gu.csv b/erpnext/translations/gu.csv
index e2de8ce..06a3cc6 100644
--- a/erpnext/translations/gu.csv
+++ b/erpnext/translations/gu.csv
@@ -7052,7 +7052,7 @@
Warranty Period (in days),(દિવસોમાં) વોરંટી સમયગાળા,
Auto re-order,ઓટો ફરી ઓર્ડર,
Reorder level based on Warehouse,વેરહાઉસ પર આધારિત પુનઃક્રમાંકિત કરો સ્તર,
-Will also apply for variants unless overrridden,Overrridden સિવાય પણ ચલો માટે લાગુ પડશે,
+Will also apply for variants unless overridden,Overrridden સિવાય પણ ચલો માટે લાગુ પડશે,
Units of Measure,માપવા એકમો,
Will also apply for variants,પણ ચલો માટે લાગુ પડશે,
Serial Nos and Batches,સીરીયલ સંખ્યા અને બૅચેસ,
diff --git a/erpnext/translations/he.csv b/erpnext/translations/he.csv
index 6cd900a..d5fcab6 100644
--- a/erpnext/translations/he.csv
+++ b/erpnext/translations/he.csv
@@ -7052,7 +7052,7 @@
Warranty Period (in days),תקופת אחריות (בימים),
Auto re-order,רכב מחדש כדי,
Reorder level based on Warehouse,רמת הזמנה חוזרת המבוסס על מחסן,
-Will also apply for variants unless overrridden,תחול גם לגרסות אלא אם overrridden,
+Will also apply for variants unless overridden,תחול גם לגרסות אלא אם overridden,
Units of Measure,יחידות מידה,
Will also apply for variants,תחול גם לגרסות,
Serial Nos and Batches,מספרים וסידורים סדרתיים,
diff --git a/erpnext/translations/hi.csv b/erpnext/translations/hi.csv
index 388b502..a5caa66 100644
--- a/erpnext/translations/hi.csv
+++ b/erpnext/translations/hi.csv
@@ -7052,7 +7052,7 @@
Warranty Period (in days),वारंटी अवधि (दिनों में),
Auto re-order,ऑटो पुनः आदेश,
Reorder level based on Warehouse,गोदाम के आधार पर पुन: व्यवस्थित स्तर,
-Will also apply for variants unless overrridden,Overrridden जब तक भी वेरिएंट के लिए लागू होगी,
+Will also apply for variants unless overridden,Overrridden जब तक भी वेरिएंट के लिए लागू होगी,
Units of Measure,मापन की इकाई,
Will also apply for variants,यह भी वेरिएंट के लिए लागू होगी,
Serial Nos and Batches,सीरियल नंबर और बैचों,
diff --git a/erpnext/translations/hr.csv b/erpnext/translations/hr.csv
index b44babc..2834602 100644
--- a/erpnext/translations/hr.csv
+++ b/erpnext/translations/hr.csv
@@ -7052,7 +7052,7 @@
Warranty Period (in days),Jamstveni period (u danima),
Auto re-order,Automatski reorganiziraj,
Reorder level based on Warehouse,Razina redoslijeda na temelju Skladište,
-Will also apply for variants unless overrridden,Također će zatražiti varijante osim overrridden,
+Will also apply for variants unless overridden,Također će zatražiti varijante osim overridden,
Units of Measure,Mjerne jedinice,
Will also apply for variants,Također će podnijeti zahtjev za varijante,
Serial Nos and Batches,Serijski brojevi i serije,
diff --git a/erpnext/translations/hu.csv b/erpnext/translations/hu.csv
index 4ea5b9a..a262c8a 100644
--- a/erpnext/translations/hu.csv
+++ b/erpnext/translations/hu.csv
@@ -7052,7 +7052,7 @@
Warranty Period (in days),Garancia hossza (napokban),
Auto re-order,Auto újra-rendelés,
Reorder level based on Warehouse,Raktárkészleten alapuló újrerendelési szint,
-Will also apply for variants unless overrridden,"Változatokra is alkalmazni fogja, hacsak nem kerül fellülírásra",
+Will also apply for variants unless overridden,"Változatokra is alkalmazni fogja, hacsak nem kerül fellülírásra",
Units of Measure,Mértékegységek,
Will also apply for variants,Változatokra is alkalmazni fogja,
Serial Nos and Batches,Sorszámok és kötegek,
diff --git a/erpnext/translations/id.csv b/erpnext/translations/id.csv
index d84c3fd..c4e50fd 100644
--- a/erpnext/translations/id.csv
+++ b/erpnext/translations/id.csv
@@ -7052,7 +7052,7 @@
Warranty Period (in days),Masa Garansi (dalam hari),
Auto re-order,Auto re-order,
Reorder level based on Warehouse,Tingkat Re-Order berdasarkan Gudang,
-Will also apply for variants unless overrridden,Juga akan berlaku untuk varian kecuali tertimpa,
+Will also apply for variants unless overridden,Juga akan berlaku untuk varian kecuali tertimpa,
Units of Measure,Satuan ukur,
Will also apply for variants,Juga akan berlaku untuk varian,
Serial Nos and Batches,Nomor Seri dan Partai,
diff --git a/erpnext/translations/is.csv b/erpnext/translations/is.csv
index 7687e4a..50c06ec 100644
--- a/erpnext/translations/is.csv
+++ b/erpnext/translations/is.csv
@@ -7052,7 +7052,7 @@
Warranty Period (in days),Ábyrgðartímabilið (í dögum),
Auto re-order,Auto endurraða,
Reorder level based on Warehouse,Uppröðun stigi byggist á Lager,
-Will also apply for variants unless overrridden,Mun einnig gilda um afbrigði nema overrridden,
+Will also apply for variants unless overridden,Mun einnig gilda um afbrigði nema overridden,
Units of Measure,Mælieiningar,
Will also apply for variants,Mun einnig gilda fyrir afbrigði,
Serial Nos and Batches,Raðnúmer og lotur,
diff --git a/erpnext/translations/it.csv b/erpnext/translations/it.csv
index b88cada..3760895 100644
--- a/erpnext/translations/it.csv
+++ b/erpnext/translations/it.csv
@@ -7052,7 +7052,7 @@
Warranty Period (in days),Periodo di garanzia (in giorni),
Auto re-order,Auto riordino,
Reorder level based on Warehouse,Livello di riordino sulla base di Magazzino,
-Will also apply for variants unless overrridden,Si applica anche per le varianti meno overrridden,
+Will also apply for variants unless overridden,Si applica anche per le varianti meno overridden,
Units of Measure,Unità di misura,
Will also apply for variants,Si applica anche per le varianti,
Serial Nos and Batches,Numero e lotti seriali,
diff --git a/erpnext/translations/ja.csv b/erpnext/translations/ja.csv
index 11455bd..888ec80 100644
--- a/erpnext/translations/ja.csv
+++ b/erpnext/translations/ja.csv
@@ -7052,7 +7052,7 @@
Warranty Period (in days),保証期間(日数),
Auto re-order,自動再注文,
Reorder level based on Warehouse,倉庫ごとの再注文レベル,
-Will also apply for variants unless overrridden,上書きされない限り、バリエーションについても適用されます,
+Will also apply for variants unless overridden,上書きされない限り、バリエーションについても適用されます,
Units of Measure,測定の単位,
Will also apply for variants,バリエーションについても適用されます,
Serial Nos and Batches,シリアル番号とバッチ,
diff --git a/erpnext/translations/km.csv b/erpnext/translations/km.csv
index 46dcaba..d2003c0 100644
--- a/erpnext/translations/km.csv
+++ b/erpnext/translations/km.csv
@@ -7052,7 +7052,7 @@
Warranty Period (in days),ការធានារយៈពេល (នៅក្នុងថ្ងៃ),
Auto re-order,ការបញ្ជាទិញជាថ្មីម្តងទៀតដោយស្វ័យប្រវត្តិ,
Reorder level based on Warehouse,កម្រិតនៃការរៀបចំដែលមានមូលដ្ឋានលើឃ្លាំង,
-Will also apply for variants unless overrridden,ក៏នឹងអនុវត្តសម្រាប់វ៉ារ្យ៉ង់បានទេលុះត្រាតែ overrridden,
+Will also apply for variants unless overridden,ក៏នឹងអនុវត្តសម្រាប់វ៉ារ្យ៉ង់បានទេលុះត្រាតែ overridden,
Units of Measure,ឯកតារង្វាស់,
Will also apply for variants,ក៏នឹងអនុវត្តសម្រាប់វ៉ារ្យ៉ង់,
Serial Nos and Batches,សៀរៀល nos និងជំនាន់,
diff --git a/erpnext/translations/kn.csv b/erpnext/translations/kn.csv
index 18e44a1..7206671 100644
--- a/erpnext/translations/kn.csv
+++ b/erpnext/translations/kn.csv
@@ -7052,7 +7052,7 @@
Warranty Period (in days),( ದಿನಗಳಲ್ಲಿ ) ಖಾತರಿ ಅವಧಿಯ,
Auto re-order,ಆಟೋ ಪುನಃ ಸಲುವಾಗಿ,
Reorder level based on Warehouse,ವೇರ್ಹೌಸ್ ಆಧರಿಸಿ ಮರುಕ್ರಮಗೊಳಿಸಿ ಮಟ್ಟದ,
-Will also apply for variants unless overrridden,Overrridden ಹೊರತು ಸಹ ರೂಪಾಂತರಗಳು ಅನ್ವಯವಾಗುವುದು,
+Will also apply for variants unless overridden,Overrridden ಹೊರತು ಸಹ ರೂಪಾಂತರಗಳು ಅನ್ವಯವಾಗುವುದು,
Units of Measure,ಮಾಪನದ ಘಟಕಗಳಿಗೆ,
Will also apply for variants,ಸಹ ರೂಪಾಂತರಗಳು ಅನ್ವಯವಾಗುವುದು,
Serial Nos and Batches,ಸೀರಿಯಲ್ ಸೂಲ ಮತ್ತು ಬ್ಯಾಚ್,
diff --git a/erpnext/translations/ko.csv b/erpnext/translations/ko.csv
index 788655c..9911925 100644
--- a/erpnext/translations/ko.csv
+++ b/erpnext/translations/ko.csv
@@ -7052,7 +7052,7 @@
Warranty Period (in days),(일) 보증 기간,
Auto re-order,자동 재 주문,
Reorder level based on Warehouse,웨어 하우스를 기반으로 재정렬 수준,
-Will also apply for variants unless overrridden,overrridden가 아니면 변형 적용됩니다,
+Will also apply for variants unless overridden,overridden가 아니면 변형 적용됩니다,
Units of Measure,측정 단위,
Will also apply for variants,또한 변형 적용됩니다,
Serial Nos and Batches,일련 번호 및 배치,
diff --git a/erpnext/translations/ku.csv b/erpnext/translations/ku.csv
index a7fcf4e..8fec059 100644
--- a/erpnext/translations/ku.csv
+++ b/erpnext/translations/ku.csv
@@ -7052,7 +7052,7 @@
Warranty Period (in days),Period Warranty (di rojên),
Auto re-order,Auto re-da,
Reorder level based on Warehouse,asta DIRTYHERTZ li ser Warehouse,
-Will also apply for variants unless overrridden,jî wê ji bo Guhertoyên serî heta overrridden,
+Will also apply for variants unless overridden,jî wê ji bo Guhertoyên serî heta overridden,
Units of Measure,Yekîneyên Measure,
Will also apply for variants,jî wê ji bo Guhertoyên serî,
Serial Nos and Batches,Serial Nos û lekerên,
diff --git a/erpnext/translations/lo.csv b/erpnext/translations/lo.csv
index 9b74f65..0831788 100644
--- a/erpnext/translations/lo.csv
+++ b/erpnext/translations/lo.csv
@@ -7052,7 +7052,7 @@
Warranty Period (in days),ໄລຍະເວລາຮັບປະກັນ (ໃນວັນເວລາ),
Auto re-order,Auto Re: ຄໍາສັ່ງ,
Reorder level based on Warehouse,ລະດັບລໍາດັບຂຶ້ນຢູ່ກັບຄັງສິນຄ້າ,
-Will also apply for variants unless overrridden,ຍັງຈະນໍາໃຊ້ສໍາລັບການ variants ເວັ້ນເສຍແຕ່ວ່າ overrridden,
+Will also apply for variants unless overridden,ຍັງຈະນໍາໃຊ້ສໍາລັບການ variants ເວັ້ນເສຍແຕ່ວ່າ overridden,
Units of Measure,ຫົວຫນ່ວຍວັດແທກ,
Will also apply for variants,ຍັງຈະນໍາໃຊ້ສໍາລັບການ variants,
Serial Nos and Batches,Serial Nos ແລະສໍາຫລັບຂະບວນ,
diff --git a/erpnext/translations/lt.csv b/erpnext/translations/lt.csv
index 2c87256..8215275 100644
--- a/erpnext/translations/lt.csv
+++ b/erpnext/translations/lt.csv
@@ -7052,7 +7052,7 @@
Warranty Period (in days),Garantinis laikotarpis (dienomis),
Auto re-order,Auto naujo užsakymas,
Reorder level based on Warehouse,Pertvarkyti lygį remiantis Warehouse,
-Will also apply for variants unless overrridden,Bus taikoma variantų nebent overrridden,
+Will also apply for variants unless overridden,Bus taikoma variantų nebent overridden,
Units of Measure,Matavimo vienetai,
Will also apply for variants,Bus taikoma variantų,
Serial Nos and Batches,Eilės Nr ir Partijos,
diff --git a/erpnext/translations/lv.csv b/erpnext/translations/lv.csv
index 2cfa130..8c4526c 100644
--- a/erpnext/translations/lv.csv
+++ b/erpnext/translations/lv.csv
@@ -7052,7 +7052,7 @@
Warranty Period (in days),Garantijas periods (dienās),
Auto re-order,Auto re-pasūtīt,
Reorder level based on Warehouse,Pārkārtot līmenis balstās uz Noliktava,
-Will also apply for variants unless overrridden,"Attieksies arī uz variantiem, ja vien overrridden",
+Will also apply for variants unless overridden,"Attieksies arī uz variantiem, ja vien overridden",
Units of Measure,Mērvienību,
Will also apply for variants,Attieksies arī uz variantiem,
Serial Nos and Batches,Sērijas Nr un Partijām,
diff --git a/erpnext/translations/mk.csv b/erpnext/translations/mk.csv
index f01b1b0..a622524 100644
--- a/erpnext/translations/mk.csv
+++ b/erpnext/translations/mk.csv
@@ -7052,7 +7052,7 @@
Warranty Period (in days),Гарантниот период (во денови),
Auto re-order,Автоматско повторно цел,
Reorder level based on Warehouse,Ниво врз основа на промените редоследот Магацински,
-Will also apply for variants unless overrridden,"Ќе се казни и варијанти, освен ако overrridden",
+Will also apply for variants unless overridden,"Ќе се казни и варијанти, освен ако overridden",
Units of Measure,На мерните единици,
Will also apply for variants,Ќе се применуваат и за варијанти,
Serial Nos and Batches,Сериски броеви и Пакетите,
diff --git a/erpnext/translations/ml.csv b/erpnext/translations/ml.csv
index 59d3160..777d5c6 100644
--- a/erpnext/translations/ml.csv
+++ b/erpnext/translations/ml.csv
@@ -7052,7 +7052,7 @@
Warranty Period (in days),(ദിവസങ്ങളിൽ) വാറന്റി കാലാവധി,
Auto re-order,ഓട്ടോ റീ-ഓർഡർ,
Reorder level based on Warehouse,വെയർഹൗസ് അടിസ്ഥാനമാക്കിയുള്ള പുനഃക്രമീകരിക്കുക തലത്തിൽ,
-Will also apply for variants unless overrridden,കൂടാതെ overrridden അവയൊഴിച്ച് മോഡലുകൾക്കാണ് ബാധകമാകും,
+Will also apply for variants unless overridden,കൂടാതെ overridden അവയൊഴിച്ച് മോഡലുകൾക്കാണ് ബാധകമാകും,
Units of Measure,അളവിന്റെ യൂണിറ്റുകൾ,
Will also apply for variants,കൂടാതെ മോഡലുകൾക്കാണ് ബാധകമാകും,
Serial Nos and Batches,സീരിയൽ എണ്ണം ബാച്ചുകളും,
diff --git a/erpnext/translations/mr.csv b/erpnext/translations/mr.csv
index ff339b6..624f1ab 100644
--- a/erpnext/translations/mr.csv
+++ b/erpnext/translations/mr.csv
@@ -7052,7 +7052,7 @@
Warranty Period (in days),(दिवस मध्ये) वॉरंटी कालावधी,
Auto re-order,ऑटो पुन्हा आदेश,
Reorder level based on Warehouse,वखारवर आधारित पुन्हा क्रमवारी लावा पातळी,
-Will also apply for variants unless overrridden,Overrridden आहेत तोपर्यंत देखील रूपे लागू राहील,
+Will also apply for variants unless overridden,Overrridden आहेत तोपर्यंत देखील रूपे लागू राहील,
Units of Measure,माप युनिट,
Will also apply for variants,तसेच रूपे लागू राहील,
Serial Nos and Batches,सिरियल क्र आणि बॅच,
diff --git a/erpnext/translations/ms.csv b/erpnext/translations/ms.csv
index 2258a18..75e150a 100644
--- a/erpnext/translations/ms.csv
+++ b/erpnext/translations/ms.csv
@@ -7052,7 +7052,7 @@
Warranty Period (in days),Tempoh jaminan (dalam hari),
Auto re-order,Auto semula perintah,
Reorder level based on Warehouse,Tahap pesanan semula berdasarkan Warehouse,
-Will also apply for variants unless overrridden,Juga akan memohon varian kecuali overrridden,
+Will also apply for variants unless overridden,Juga akan memohon varian kecuali overridden,
Units of Measure,Unit ukuran,
Will also apply for variants,Juga akan memohon varian,
Serial Nos and Batches,Serial Nos dan Kelompok,
diff --git a/erpnext/translations/my.csv b/erpnext/translations/my.csv
index dc5ab12..36cd874 100644
--- a/erpnext/translations/my.csv
+++ b/erpnext/translations/my.csv
@@ -7052,7 +7052,7 @@
Warranty Period (in days),(ရက်) ကိုအာမခံကာလ,
Auto re-order,မော်တော်ကားပြန်လည်အမိန့်,
Reorder level based on Warehouse,ဂိုဒေါင်အပေါ်အခြေခံပြီး reorder level ကို,
-Will also apply for variants unless overrridden,စ overrridden မဟုတ်လျှင်မျိုးကွဲလျှောက်ထားလိမ့်မည်ဟု,
+Will also apply for variants unless overridden,စ overridden မဟုတ်လျှင်မျိုးကွဲလျှောက်ထားလိမ့်မည်ဟု,
Units of Measure,တိုင်း၏ယူနစ်,
Will also apply for variants,စမျိုးကွဲလျှောက်ထားလိမ့်မည်ဟု,
Serial Nos and Batches,serial Nos နှင့် batch,
diff --git a/erpnext/translations/nl.csv b/erpnext/translations/nl.csv
index ad11eae..5859833 100644
--- a/erpnext/translations/nl.csv
+++ b/erpnext/translations/nl.csv
@@ -7052,7 +7052,7 @@
Warranty Period (in days),Garantieperiode (in dagen),
Auto re-order,Auto re-order,
Reorder level based on Warehouse,Bestelniveau gebaseerd op Warehouse,
-Will also apply for variants unless overrridden,Geldt ook voor varianten tenzij overrridden,
+Will also apply for variants unless overridden,Geldt ook voor varianten tenzij overridden,
Units of Measure,Meeteenheden,
Will also apply for variants,Geldt ook voor varianten,
Serial Nos and Batches,Serienummers en batches,
diff --git a/erpnext/translations/no.csv b/erpnext/translations/no.csv
index b136e97..a3236ac 100644
--- a/erpnext/translations/no.csv
+++ b/erpnext/translations/no.csv
@@ -7052,7 +7052,7 @@
Warranty Period (in days),Garantiperioden (i dager),
Auto re-order,Auto re-order,
Reorder level based on Warehouse,Omgjøre nivå basert på Warehouse,
-Will also apply for variants unless overrridden,Vil også gjelde for varianter med mindre overrridden,
+Will also apply for variants unless overridden,Vil også gjelde for varianter med mindre overridden,
Units of Measure,Måleenheter,
Will also apply for variants,Vil også gjelde for varianter,
Serial Nos and Batches,Serienummer og partier,
diff --git a/erpnext/translations/pl.csv b/erpnext/translations/pl.csv
index 9be56f3..df41e39 100644
--- a/erpnext/translations/pl.csv
+++ b/erpnext/translations/pl.csv
@@ -6987,7 +6987,7 @@
Warranty Period (in days),Okres gwarancji (w dniach),
Auto re-order,Automatyczne ponowne zamówienie,
Reorder level based on Warehouse,Zmiana kolejności w oparciu o poziom Magazynu,
-Will also apply for variants unless overrridden,"Również zostanie zastosowany do wariantów, chyba że zostanie nadpisany",
+Will also apply for variants unless overridden,"Również zostanie zastosowany do wariantów, chyba że zostanie nadpisany",
Units of Measure,Jednostki miary,
Will also apply for variants,Również zastosowanie do wariantów,
Serial Nos and Batches,Numery seryjne i partie,
diff --git a/erpnext/translations/ps.csv b/erpnext/translations/ps.csv
index 8033752..5a0b2a5 100644
--- a/erpnext/translations/ps.csv
+++ b/erpnext/translations/ps.csv
@@ -7052,7 +7052,7 @@
Warranty Period (in days),ګرنټی د دورې (په ورځو),
Auto re-order,د موټرونو د بيا نظم,
Reorder level based on Warehouse,ترمیمي په کچه د پر بنسټ د ګدام,
-Will also apply for variants unless overrridden,مګر overrridden به د بېرغونو هم تر غوږو,
+Will also apply for variants unless overridden,مګر overridden به د بېرغونو هم تر غوږو,
Units of Measure,د اندازه کولو واحدونه,
Will also apply for variants,به هم د بېرغونو درخواست,
Serial Nos and Batches,سریال وځيري او دستو,
diff --git a/erpnext/translations/pt-BR.csv b/erpnext/translations/pt-BR.csv
index 9823470..bc5b616 100644
--- a/erpnext/translations/pt-BR.csv
+++ b/erpnext/translations/pt-BR.csv
@@ -7052,7 +7052,7 @@
Warranty Period (in days),Período de Garantia (em dias),
Auto re-order,Reposição Automática,
Reorder level based on Warehouse,Nível de reposição baseado no Armazén,
-Will also apply for variants unless overrridden,Também se aplica a variantes a não ser que seja sobrescrito,
+Will also apply for variants unless overridden,Também se aplica a variantes a não ser que seja sobrescrito,
Units of Measure,Unidades de Medida,
Will also apply for variants,Também se aplica às variantes,
Serial Nos and Batches,Números de Série e Lotes,
diff --git a/erpnext/translations/pt.csv b/erpnext/translations/pt.csv
index c2afe32..e6846c6 100644
--- a/erpnext/translations/pt.csv
+++ b/erpnext/translations/pt.csv
@@ -7052,7 +7052,7 @@
Warranty Period (in days),Período de Garantia (em dias),
Auto re-order,Voltar a Pedir Autom.,
Reorder level based on Warehouse,Nível de reencomenda no Armazém,
-Will also apply for variants unless overrridden,Também se aplica para as variantes a menos que seja anulado,
+Will also apply for variants unless overridden,Também se aplica para as variantes a menos que seja anulado,
Units of Measure,Unidades de medida,
Will also apply for variants,Também se aplicará para as variantes,
Serial Nos and Batches,Números de série e lotes,
diff --git a/erpnext/translations/ro.csv b/erpnext/translations/ro.csv
index 0cb3f84..ac7e598 100644
--- a/erpnext/translations/ro.csv
+++ b/erpnext/translations/ro.csv
@@ -7052,7 +7052,7 @@
Warranty Period (in days),Perioada de garanție (în zile),
Auto re-order,Re-comandă automată,
Reorder level based on Warehouse,Nivel pentru re-comanda bazat pe Magazie,
-Will also apply for variants unless overrridden,Se va aplica și pentru variantele cu excepția cazului în overrridden,
+Will also apply for variants unless overridden,Se va aplica și pentru variantele cu excepția cazului în overridden,
Units of Measure,Unitati de masura,
Will also apply for variants,"Va aplică, de asemenea pentru variante",
Serial Nos and Batches,Numere și loturi seriale,
diff --git a/erpnext/translations/ru.csv b/erpnext/translations/ru.csv
index da4e1be..52c2998 100644
--- a/erpnext/translations/ru.csv
+++ b/erpnext/translations/ru.csv
@@ -6985,7 +6985,7 @@
Warranty Period (in days),Гарантийный период (дней),
Auto re-order,Автоматический перезаказ,
Reorder level based on Warehouse,Уровень переупорядочивания на основе склада,
-Will also apply for variants unless overrridden,"Будет также применяться для модификаций, если не отменено",
+Will also apply for variants unless overridden,"Будет также применяться для модификаций, если не отменено",
Units of Measure,Единицы измерения,
Will also apply for variants,Также применять к модификациям,
Serial Nos and Batches,Серийные номера и партии,
diff --git a/erpnext/translations/rw.csv b/erpnext/translations/rw.csv
index ae0cb3a..f035d57 100644
--- a/erpnext/translations/rw.csv
+++ b/erpnext/translations/rw.csv
@@ -7052,7 +7052,7 @@
Warranty Period (in days),Igihe cya garanti (muminsi),
Auto re-order,Ongera utumire,
Reorder level based on Warehouse,Urwego rwo kwisubiramo rushingiye kububiko,
-Will also apply for variants unless overrridden,Uzasaba kandi kubitandukanye keretse birenze,
+Will also apply for variants unless overridden,Uzasaba kandi kubitandukanye keretse birenze,
Units of Measure,Ibipimo,
Will also apply for variants,Uzasaba kandi kubitandukanye,
Serial Nos and Batches,Urutonde Nomero,
diff --git a/erpnext/translations/si.csv b/erpnext/translations/si.csv
index fa6fbf0..4047263 100644
--- a/erpnext/translations/si.csv
+++ b/erpnext/translations/si.csv
@@ -7052,7 +7052,7 @@
Warranty Period (in days),වගකීම් කාලය (දින තුළ),
Auto re-order,වාහන නැවත අනුපිළිවෙලට,
Reorder level based on Warehouse,ගබඩාව මත පදනම් මොහොත මට්ටමේ,
-Will also apply for variants unless overrridden,ද overrridden මිස ප්රභේද සඳහා අයදුම් කරනු ඇත,
+Will also apply for variants unless overridden,ද overridden මිස ප්රභේද සඳහා අයදුම් කරනු ඇත,
Units of Measure,නු ඒකක,
Will also apply for variants,ද ප්රභේද සඳහා අයදුම් කරනු ඇත,
Serial Nos and Batches,අනුක්රමික අංක සහ කාණ්ඩ,
diff --git a/erpnext/translations/sk.csv b/erpnext/translations/sk.csv
index 0e51158..98e1663 100644
--- a/erpnext/translations/sk.csv
+++ b/erpnext/translations/sk.csv
@@ -7052,7 +7052,7 @@
Warranty Period (in days),Záruční doba (ve dnech),
Auto re-order,Auto re-order,
Reorder level based on Warehouse,Úroveň Zmena poradia na základe Warehouse,
-Will also apply for variants unless overrridden,"Bude platiť aj pre varianty, pokiaľ nebude prepísané",
+Will also apply for variants unless overridden,"Bude platiť aj pre varianty, pokiaľ nebude prepísané",
Units of Measure,merné jednotky,
Will also apply for variants,Bude platiť aj pre varianty,
Serial Nos and Batches,Sériové čísla a dávky,
diff --git a/erpnext/translations/sl.csv b/erpnext/translations/sl.csv
index 7c4e11b..5380714 100644
--- a/erpnext/translations/sl.csv
+++ b/erpnext/translations/sl.csv
@@ -7052,7 +7052,7 @@
Warranty Period (in days),Garancijski rok (v dnevih),
Auto re-order,Auto re-order,
Reorder level based on Warehouse,Raven Preureditev temelji na Warehouse,
-Will also apply for variants unless overrridden,Bo veljalo tudi za variante razen overrridden,
+Will also apply for variants unless overridden,Bo veljalo tudi za variante razen overridden,
Units of Measure,Merske enote,
Will also apply for variants,Bo veljalo tudi za variante,
Serial Nos and Batches,Serijska št in Serije,
diff --git a/erpnext/translations/sq.csv b/erpnext/translations/sq.csv
index 0f10795..2a893d2 100644
--- a/erpnext/translations/sq.csv
+++ b/erpnext/translations/sq.csv
@@ -7052,7 +7052,7 @@
Warranty Period (in days),Garanci Periudha (në ditë),
Auto re-order,Auto ri-qëllim,
Reorder level based on Warehouse,Niveli Reorder bazuar në Magazina,
-Will also apply for variants unless overrridden,Gjithashtu do të aplikojë për variantet nëse overrridden,
+Will also apply for variants unless overridden,Gjithashtu do të aplikojë për variantet nëse overridden,
Units of Measure,Njësitë e masës,
Will also apply for variants,Gjithashtu do të aplikojë për variantet,
Serial Nos and Batches,Serial Nr dhe Batches,
diff --git a/erpnext/translations/sr.csv b/erpnext/translations/sr.csv
index 38116ec..c1e5eb0 100644
--- a/erpnext/translations/sr.csv
+++ b/erpnext/translations/sr.csv
@@ -7052,7 +7052,7 @@
Warranty Period (in days),Гарантни период (у данима),
Auto re-order,Ауто поново реда,
Reorder level based on Warehouse,Промени редослед ниво на основу Варехоусе,
-Will also apply for variants unless overrridden,Ће конкурисати и за варијанте осим оверрридден,
+Will also apply for variants unless overridden,Ће конкурисати и за варијанте осим оверрридден,
Units of Measure,Мерних јединица,
Will also apply for variants,Ће конкурисати и за варијанте,
Serial Nos and Batches,Сериал Нос анд Пакети,
diff --git a/erpnext/translations/sv.csv b/erpnext/translations/sv.csv
index c4d46ea..8b4ab06 100644
--- a/erpnext/translations/sv.csv
+++ b/erpnext/translations/sv.csv
@@ -7052,7 +7052,7 @@
Warranty Period (in days),Garantitiden (i dagar),
Auto re-order,Auto återbeställning,
Reorder level based on Warehouse,Beställningsnivå baserat på Warehouse,
-Will also apply for variants unless overrridden,Kommer också att ansöka om varianter såvida inte överskriden,
+Will also apply for variants unless overridden,Kommer också att ansöka om varianter såvida inte överskriden,
Units of Measure,Måttenheter,
Will also apply for variants,Kommer också att ansöka om varianter,
Serial Nos and Batches,Serienummer och partier,
diff --git a/erpnext/translations/sw.csv b/erpnext/translations/sw.csv
index ad144f0..fa2287c 100644
--- a/erpnext/translations/sw.csv
+++ b/erpnext/translations/sw.csv
@@ -7052,7 +7052,7 @@
Warranty Period (in days),Kipindi cha udhamini (katika siku),
Auto re-order,Rejesha upya,
Reorder level based on Warehouse,Weka upya ngazi kulingana na Ghala,
-Will also apply for variants unless overrridden,Pia itatumika kwa vipengee isipokuwa imeingizwa,
+Will also apply for variants unless overridden,Pia itatumika kwa vipengee isipokuwa imeingizwa,
Units of Measure,Units of Measure,
Will also apply for variants,Pia itatumika kwa vipengee,
Serial Nos and Batches,Serial Nos na Batches,
diff --git a/erpnext/translations/ta.csv b/erpnext/translations/ta.csv
index 5ccabc0..6eaae34 100644
--- a/erpnext/translations/ta.csv
+++ b/erpnext/translations/ta.csv
@@ -7052,7 +7052,7 @@
Warranty Period (in days),உத்தரவாதத்தை காலம் (நாட்கள்),
Auto re-order,வாகன மறு ஒழுங்கு,
Reorder level based on Warehouse,கிடங்கில் அடிப்படையில் மறுவரிசைப்படுத்துக நிலை,
-Will also apply for variants unless overrridden,Overrridden வரை கூட வகைகளில் விண்ணப்பிக்க,
+Will also apply for variants unless overridden,Overrridden வரை கூட வகைகளில் விண்ணப்பிக்க,
Units of Measure,அளவின் அலகுகள்,
Will also apply for variants,கூட வகைகளில் விண்ணப்பிக்க,
Serial Nos and Batches,சீரியல் எண்கள் மற்றும் தொகுப்புகளும்,
diff --git a/erpnext/translations/te.csv b/erpnext/translations/te.csv
index 8472163..d3f739a 100644
--- a/erpnext/translations/te.csv
+++ b/erpnext/translations/te.csv
@@ -7052,7 +7052,7 @@
Warranty Period (in days),(రోజుల్లో) వారంటీ వ్యవధి,
Auto re-order,ఆటో క్రమాన్ని,
Reorder level based on Warehouse,వేర్హౌస్ ఆధారంగా క్రమాన్ని స్థాయి,
-Will also apply for variants unless overrridden,Overrridden తప్ప కూడా రూపాంతరాలు వర్తిస్తాయని,
+Will also apply for variants unless overridden,Overrridden తప్ప కూడా రూపాంతరాలు వర్తిస్తాయని,
Units of Measure,యూనిట్స్ ఆఫ్ మెజర్,
Will also apply for variants,కూడా రూపాంతరాలు వర్తిస్తాయని,
Serial Nos and Batches,సీరియల్ Nos మరియు ఇస్తున్న,
diff --git a/erpnext/translations/th.csv b/erpnext/translations/th.csv
index dcd632b..a065595 100644
--- a/erpnext/translations/th.csv
+++ b/erpnext/translations/th.csv
@@ -7052,7 +7052,7 @@
Warranty Period (in days),ระยะเวลารับประกัน (วัน),
Auto re-order,Auto สั่งซื้อใหม่,
Reorder level based on Warehouse,ระดับสั่งซื้อใหม่บนพื้นฐานของคลังสินค้า,
-Will also apply for variants unless overrridden,นอกจากนี้ยังจะใช้สำหรับสายพันธุ์เว้นแต่ overrridden,
+Will also apply for variants unless overridden,นอกจากนี้ยังจะใช้สำหรับสายพันธุ์เว้นแต่ overridden,
Units of Measure,หน่วยวัด,
Will also apply for variants,นอกจากนี้ยังจะใช้สำหรับสายพันธุ์,
Serial Nos and Batches,หมายเลขและชุดเลขที่ผลิตภัณฑ์,
diff --git a/erpnext/translations/tr.csv b/erpnext/translations/tr.csv
index 3708246..9e916f0 100644
--- a/erpnext/translations/tr.csv
+++ b/erpnext/translations/tr.csv
@@ -7051,7 +7051,7 @@
Warranty Period (in days),Garanti Süresi (gün),
Auto re-order,Otomatik Yeniden Sipariş,
Reorder level based on Warehouse,Depo bazlı Yeniden sipariş seviyesi,
-Will also apply for variants unless overrridden,Geçersiz kılınmadığı sürece varyantlar için de geçerli olacaktır.,
+Will also apply for variants unless overridden,Geçersiz kılınmadığı sürece varyantlar için de geçerli olacaktır.,
Units of Measure,Ölçü Birimleri,
Will also apply for variants,Varyantlar için de geçerli olacak,
Serial Nos and Batches,Seri No ve Batches (Parti),
diff --git a/erpnext/translations/uk.csv b/erpnext/translations/uk.csv
index 1752330..8d1fb04 100644
--- a/erpnext/translations/uk.csv
+++ b/erpnext/translations/uk.csv
@@ -7052,7 +7052,7 @@
Warranty Period (in days),Гарантійний термін (в днях),
Auto re-order,Авто-дозамовлення,
Reorder level based on Warehouse,Рівень перезамовлення по складу,
-Will also apply for variants unless overrridden,"Буде також застосовуватися для варіантів, якщо не перевказано",
+Will also apply for variants unless overridden,"Буде також застосовуватися для варіантів, якщо не перевказано",
Units of Measure,одиниці виміру,
Will also apply for variants,Буде також застосовуватися для варіантів,
Serial Nos and Batches,Серійні номери і Порції,
diff --git a/erpnext/translations/ur.csv b/erpnext/translations/ur.csv
index 504cc8d..649c1c7 100644
--- a/erpnext/translations/ur.csv
+++ b/erpnext/translations/ur.csv
@@ -7052,7 +7052,7 @@
Warranty Period (in days),(دن میں) وارنٹی مدت,
Auto re-order,آٹو دوبارہ آرڈر,
Reorder level based on Warehouse,گودام کی بنیاد پر ترتیب کی سطح کو منتخب,
-Will also apply for variants unless overrridden,overrridden جب تک بھی مختلف حالتوں کے لئے لاگو ہوں گے,
+Will also apply for variants unless overridden,overridden جب تک بھی مختلف حالتوں کے لئے لاگو ہوں گے,
Units of Measure,پیمائش کی اکائیوں,
Will also apply for variants,بھی مختلف حالتوں کے لئے لاگو ہوں گے,
Serial Nos and Batches,سیریل نمبر اور بیچوں,
diff --git a/erpnext/translations/uz.csv b/erpnext/translations/uz.csv
index 6b25e7b..5ca51cc 100644
--- a/erpnext/translations/uz.csv
+++ b/erpnext/translations/uz.csv
@@ -7052,7 +7052,7 @@
Warranty Period (in days),Kafolat muddati (kunlar),
Auto re-order,Avtomatik buyurtma,
Reorder level based on Warehouse,Qoidalarga asoslangan qayta tartiblash,
-Will also apply for variants unless overrridden,"Variantlar uchun ham qo'llanilmaydi, agar bekor qilinsa",
+Will also apply for variants unless overridden,"Variantlar uchun ham qo'llanilmaydi, agar bekor qilinsa",
Units of Measure,O'lchov birliklari,
Will also apply for variants,"Shuningdek, variantlar uchun ham qo'llaniladi",
Serial Nos and Batches,Seriya nos va paketlar,
diff --git a/erpnext/translations/vi.csv b/erpnext/translations/vi.csv
index e576ef7..7a005fa 100644
--- a/erpnext/translations/vi.csv
+++ b/erpnext/translations/vi.csv
@@ -7052,7 +7052,7 @@
Warranty Period (in days),Thời gian bảo hành (trong...ngày),
Auto re-order,Auto lại trật tự,
Reorder level based on Warehouse,mức đèn đỏ mua vật tư (phải bổ xung hoặc đặt mua thêm),
-Will also apply for variants unless overrridden,Cũng sẽ được áp dụng cho các biến thể trừ phần bị ghi đèn,
+Will also apply for variants unless overridden,Cũng sẽ được áp dụng cho các biến thể trừ phần bị ghi đèn,
Units of Measure,Đơn vị đo lường,
Will also apply for variants,Cũng sẽ được áp dụng cho các biến thể,
Serial Nos and Batches,Số hàng loạt và hàng loạt,
diff --git a/erpnext/translations/zh-TW.csv b/erpnext/translations/zh-TW.csv
index 699d802..0f76e97 100644
--- a/erpnext/translations/zh-TW.csv
+++ b/erpnext/translations/zh-TW.csv
@@ -2964,7 +2964,7 @@
Code {0} already exist,代碼{0}已經存在
Sales orders are not available for production,銷售訂單不可用於生產
Fixed Asset Depreciation Settings,固定資產折舊設置
-Will also apply for variants unless overrridden,同時將申請變種,除非overrridden,
+Will also apply for variants unless overridden,同時將申請變種,除非overridden,
Advances,進展
Manufacture against Material Request,對製造材料要求
Assessment Group: ,評估組:
diff --git a/erpnext/translations/zh.csv b/erpnext/translations/zh.csv
index 70ec81a..1d8a261 100644
--- a/erpnext/translations/zh.csv
+++ b/erpnext/translations/zh.csv
@@ -7052,7 +7052,7 @@
Warranty Period (in days),保修期限(天数),
Auto re-order,自动重订货,
Reorder level based on Warehouse,根据仓库订货点水平,
-Will also apply for variants unless overrridden,除非手动指定,否则会同时应用于变体,
+Will also apply for variants unless overridden,除非手动指定,否则会同时应用于变体,
Units of Measure,计量单位,
Will also apply for variants,会同时应用于变体,
Serial Nos and Batches,序列号和批号,
diff --git a/erpnext/translations/zh_tw.csv b/erpnext/translations/zh_tw.csv
index 75157f0..8ecbaaa 100644
--- a/erpnext/translations/zh_tw.csv
+++ b/erpnext/translations/zh_tw.csv
@@ -7485,7 +7485,7 @@
Warranty Period (in days),保修期限(天數),
Auto re-order,自動重新排序,
Reorder level based on Warehouse,根據倉庫訂貨點水平,
-Will also apply for variants unless overrridden,同時將申請變種,除非overrridden,
+Will also apply for variants unless overridden,同時將申請變種,除非overridden,
Units of Measure,測量的單位,
Will also apply for variants,同時將申請變種,
Serial Nos and Batches,序列號和批號,