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

chore: release v15
This commit is contained in:
Deepesh Garg 2023-11-14 18:52:01 +05:30 committed by GitHub
commit 9f9a4a9eab
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
111 changed files with 629 additions and 309 deletions

View File

@ -53,10 +53,18 @@ frappe.ui.form.on('Chart of Accounts Importer', {
of Accounts. Please enter the account names and add more rows as per your requirement.`);
}
}
}
},
{
label : "Company",
fieldname: "company",
fieldtype: "Link",
reqd: 1,
hidden: 1,
default: frm.doc.company,
},
],
primary_action: function() {
var data = d.get_values();
let data = d.get_values();
if (!data.template_type) {
frappe.throw(__('Please select <b>Template Type</b> to download template'));
@ -66,7 +74,8 @@ frappe.ui.form.on('Chart of Accounts Importer', {
'/api/method/erpnext.accounts.doctype.chart_of_accounts_importer.chart_of_accounts_importer.download_template',
{
file_type: data.file_type,
template_type: data.template_type
template_type: data.template_type,
company: data.company
}
);

View File

@ -8,6 +8,7 @@ from functools import reduce
import frappe
from frappe import _
from frappe.desk.form.linked_with import get_linked_fields
from frappe.model.document import Document
from frappe.utils import cint, cstr
from frappe.utils.csvutils import UnicodeWriter
@ -294,10 +295,8 @@ def build_response_as_excel(writer):
@frappe.whitelist()
def download_template(file_type, template_type):
data = frappe._dict(frappe.local.form_dict)
writer = get_template(template_type)
def download_template(file_type, template_type, company):
writer = get_template(template_type, company)
if file_type == "CSV":
# download csv file
@ -308,8 +307,7 @@ def download_template(file_type, template_type):
build_response_as_excel(writer)
def get_template(template_type):
def get_template(template_type, company):
fields = [
"Account Name",
"Parent Account",
@ -335,34 +333,17 @@ def get_template(template_type):
["", "", "", "", 0, account_type.get("account_type"), account_type.get("root_type")]
)
else:
writer = get_sample_template(writer)
writer = get_sample_template(writer, company)
return writer
def get_sample_template(writer):
template = [
["Application Of Funds(Assets)", "", "", "", 1, "", "Asset"],
["Sources Of Funds(Liabilities)", "", "", "", 1, "", "Liability"],
["Equity", "", "", "", 1, "", "Equity"],
["Expenses", "", "", "", 1, "", "Expense"],
["Income", "", "", "", 1, "", "Income"],
["Bank Accounts", "Application Of Funds(Assets)", "", "", 1, "Bank", "Asset"],
["Cash In Hand", "Application Of Funds(Assets)", "", "", 1, "Cash", "Asset"],
["Stock Assets", "Application Of Funds(Assets)", "", "", 1, "Stock", "Asset"],
["Cost Of Goods Sold", "Expenses", "", "", 0, "Cost of Goods Sold", "Expense"],
["Asset Depreciation", "Expenses", "", "", 0, "Depreciation", "Expense"],
["Fixed Assets", "Application Of Funds(Assets)", "", "", 0, "Fixed Asset", "Asset"],
["Accounts Payable", "Sources Of Funds(Liabilities)", "", "", 0, "Payable", "Liability"],
["Accounts Receivable", "Application Of Funds(Assets)", "", "", 1, "Receivable", "Asset"],
["Stock Expenses", "Expenses", "", "", 0, "Stock Adjustment", "Expense"],
["Sample Bank", "Bank Accounts", "", "", 0, "Bank", "Asset"],
["Cash", "Cash In Hand", "", "", 0, "Cash", "Asset"],
["Stores", "Stock Assets", "", "", 0, "Stock", "Asset"],
]
for row in template:
writer.writerow(row)
def get_sample_template(writer, company):
currency = frappe.db.get_value("Company", company, "default_currency")
with open(os.path.join(os.path.dirname(__file__), "coa_sample_template.csv"), "r") as f:
for row in f:
row = row.strip().split(",") + [currency]
writer.writerow(row)
return writer
@ -453,14 +434,11 @@ def get_mandatory_account_types():
def unset_existing_data(company):
linked = frappe.db.sql(
'''select fieldname from tabDocField
where fieldtype="Link" and options="Account" and parent="Company"''',
as_dict=True,
)
# remove accounts data from company
update_values = {d.fieldname: "" for d in linked}
fieldnames = get_linked_fields("Account").get("Company", {}).get("fieldname", [])
linked = [{"fieldname": name} for name in fieldnames]
update_values = {d.get("fieldname"): "" for d in linked}
frappe.db.set_value("Company", company, update_values, update_values)
# remove accounts data from various doctypes

View File

@ -0,0 +1,17 @@
Application Of Funds(Assets),,,,1,,Asset
Sources Of Funds(Liabilities),,,,1,,Liability
Equity,,,,1,,Equity
Expenses,,,,1,Expense Account,Expense
Income,,,,1,Income Account,Income
Bank Accounts,Application Of Funds(Assets),,,1,Bank,Asset
Cash In Hand,Application Of Funds(Assets),,,1,Cash,Asset
Stock Assets,Application Of Funds(Assets),,,1,Stock,Asset
Cost Of Goods Sold,Expenses,,,0,Cost of Goods Sold,Expense
Asset Depreciation,Expenses,,,0,Depreciation,Expense
Fixed Assets,Application Of Funds(Assets),,,0,Fixed Asset,Asset
Accounts Payable,Sources Of Funds(Liabilities),,,0,Payable,Liability
Accounts Receivable,Application Of Funds(Assets),,,1,Receivable,Asset
Stock Expenses,Expenses,,,0,Stock Adjustment,Expense
Sample Bank,Bank Accounts,,,0,Bank,Asset
Cash,Cash In Hand,,,0,Cash,Asset
Stores,Stock Assets,,,0,Stock,Asset
1 Application Of Funds(Assets) 1 Asset
2 Sources Of Funds(Liabilities) 1 Liability
3 Equity 1 Equity
4 Expenses 1 Expense Account Expense
5 Income 1 Income Account Income
6 Bank Accounts Application Of Funds(Assets) 1 Bank Asset
7 Cash In Hand Application Of Funds(Assets) 1 Cash Asset
8 Stock Assets Application Of Funds(Assets) 1 Stock Asset
9 Cost Of Goods Sold Expenses 0 Cost of Goods Sold Expense
10 Asset Depreciation Expenses 0 Depreciation Expense
11 Fixed Assets Application Of Funds(Assets) 0 Fixed Asset Asset
12 Accounts Payable Sources Of Funds(Liabilities) 0 Payable Liability
13 Accounts Receivable Application Of Funds(Assets) 1 Receivable Asset
14 Stock Expenses Expenses 0 Stock Adjustment Expense
15 Sample Bank Bank Accounts 0 Bank Asset
16 Cash Cash In Hand 0 Cash Asset
17 Stores Stock Assets 0 Stock Asset

View File

@ -595,6 +595,7 @@
"fieldname": "status",
"fieldtype": "Select",
"label": "Status",
"no_copy": 1,
"options": "\nDraft\nSubmitted\nCancelled",
"read_only": 1
},
@ -750,7 +751,7 @@
"index_web_pages_for_search": 1,
"is_submittable": 1,
"links": [],
"modified": "2023-06-23 18:07:38.023010",
"modified": "2023-11-08 21:51:03.482709",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Payment Entry",

View File

@ -33,6 +33,7 @@ from erpnext.accounts.utils import (
get_account_currency,
get_balance_on,
get_outstanding_invoices,
get_party_types_from_account_type,
)
from erpnext.controllers.accounts_controller import (
AccountsController,
@ -83,7 +84,6 @@ class PaymentEntry(AccountsController):
self.apply_taxes()
self.set_amounts_after_tax()
self.clear_unallocated_reference_document_rows()
self.validate_payment_against_negative_invoice()
self.validate_transaction_reference()
self.set_title()
self.set_remarks()
@ -952,35 +952,6 @@ class PaymentEntry(AccountsController):
self.name,
)
def validate_payment_against_negative_invoice(self):
if (self.payment_type != "Pay" or self.party_type != "Customer") and (
self.payment_type != "Receive" or self.party_type != "Supplier"
):
return
total_negative_outstanding = sum(
abs(flt(d.outstanding_amount)) for d in self.get("references") if flt(d.outstanding_amount) < 0
)
paid_amount = self.paid_amount if self.payment_type == "Receive" else self.received_amount
additional_charges = sum(flt(d.amount) for d in self.deductions)
if not total_negative_outstanding:
if self.party_type == "Customer":
msg = _("Cannot pay to Customer without any negative outstanding invoice")
else:
msg = _("Cannot receive from Supplier without any negative outstanding invoice")
frappe.throw(msg, InvalidPaymentEntry)
elif paid_amount - additional_charges > total_negative_outstanding:
frappe.throw(
_("Paid Amount cannot be greater than total negative outstanding amount {0}").format(
fmt_money(total_negative_outstanding)
),
InvalidPaymentEntry,
)
def set_title(self):
if frappe.flags.in_import and self.title:
# do not set title dynamically if title exists during data import.
@ -1083,9 +1054,7 @@ class PaymentEntry(AccountsController):
item=self,
)
dr_or_cr = (
"credit" if erpnext.get_party_account_type(self.party_type) == "Receivable" else "debit"
)
dr_or_cr = "credit" if self.payment_type == "Receive" else "debit"
for d in self.get("references"):
cost_center = self.cost_center
@ -1103,10 +1072,27 @@ class PaymentEntry(AccountsController):
against_voucher_type = d.reference_doctype
against_voucher = d.reference_name
reverse_dr_or_cr, standalone_note = 0, 0
if d.reference_doctype in ["Sales Invoice", "Purchase Invoice"]:
is_return, return_against = frappe.db.get_value(
d.reference_doctype, d.reference_name, ["is_return", "return_against"]
)
payable_party_types = get_party_types_from_account_type("Payable")
receivable_party_types = get_party_types_from_account_type("Receivable")
if is_return and self.party_type in receivable_party_types and (self.payment_type == "Pay"):
reverse_dr_or_cr = 1
elif (
is_return and self.party_type in payable_party_types and (self.payment_type == "Receive")
):
reverse_dr_or_cr = 1
if is_return and not return_against and not reverse_dr_or_cr:
dr_or_cr = "debit" if dr_or_cr == "credit" else "credit"
gle.update(
{
dr_or_cr: allocated_amount_in_company_currency,
dr_or_cr + "_in_account_currency": d.allocated_amount,
dr_or_cr: abs(allocated_amount_in_company_currency),
dr_or_cr + "_in_account_currency": abs(d.allocated_amount),
"against_voucher_type": against_voucher_type,
"against_voucher": against_voucher,
"cost_center": cost_center,

View File

@ -683,17 +683,6 @@ class TestPaymentEntry(FrappeTestCase):
self.validate_gl_entries(pe.name, expected_gle)
def test_payment_against_negative_sales_invoice(self):
pe1 = frappe.new_doc("Payment Entry")
pe1.payment_type = "Pay"
pe1.company = "_Test Company"
pe1.party_type = "Customer"
pe1.party = "_Test Customer"
pe1.paid_from = "_Test Cash - _TC"
pe1.paid_amount = 100
pe1.received_amount = 100
self.assertRaises(InvalidPaymentEntry, pe1.validate)
si1 = create_sales_invoice()
# create full payment entry against si1
@ -751,8 +740,6 @@ class TestPaymentEntry(FrappeTestCase):
# pay more than outstanding against si1
pe3 = get_payment_entry("Sales Invoice", si1.name, bank_account="_Test Cash - _TC")
pe3.paid_amount = pe3.received_amount = 300
self.assertRaises(InvalidPaymentEntry, pe3.validate)
# pay negative outstanding against si1
pe3.paid_to = "Debtors - _TC"
@ -1262,6 +1249,39 @@ class TestPaymentEntry(FrappeTestCase):
so.reload()
self.assertEqual(so.advance_paid, so.rounded_total)
def test_receive_payment_from_payable_party_type(self):
pe = create_payment_entry(
party_type="Supplier",
party="_Test Supplier",
payment_type="Receive",
paid_from="Creditors - _TC",
paid_to="_Test Cash - _TC",
save=True,
submit=True,
)
self.voucher_no = pe.name
self.expected_gle = [
{"account": "_Test Cash - _TC", "debit": 1000.0, "credit": 0.0},
{"account": "Creditors - _TC", "debit": 0.0, "credit": 1000.0},
]
self.check_gl_entries()
def check_gl_entries(self):
gle = frappe.qb.DocType("GL Entry")
gl_entries = (
frappe.qb.from_(gle)
.select(
gle.account,
gle.debit,
gle.credit,
)
.where((gle.voucher_no == self.voucher_no) & (gle.is_cancelled == 0))
.orderby(gle.account)
).run(as_dict=True)
for row in range(len(self.expected_gle)):
for field in ["account", "debit", "credit"]:
self.assertEqual(self.expected_gle[row][field], gl_entries[row][field])
def create_payment_entry(**args):
payment_entry = frappe.new_doc("Payment Entry")

View File

@ -187,7 +187,6 @@ erpnext.accounts.SalesInvoiceController = class SalesInvoiceController extends e
erpnext.accounts.unreconcile_payments.add_unreconcile_btn(me.frm);
}
make_maintenance_schedule() {
frappe.model.open_mapped_doc({
method: "erpnext.accounts.doctype.sales_invoice.sales_invoice.make_maintenance_schedule",
@ -563,15 +562,6 @@ cur_frm.fields_dict.write_off_cost_center.get_query = function(doc) {
}
}
// Income Account in Details Table
// --------------------------------
cur_frm.set_query("income_account", "items", function(doc) {
return{
query: "erpnext.controllers.queries.get_income_account",
filters: {'company': doc.company}
}
});
// Cost Center in Details Table
// -----------------------------
cur_frm.fields_dict["items"].grid.get_field("cost_center").get_query = function(doc) {
@ -666,6 +656,16 @@ frappe.ui.form.on('Sales Invoice', {
};
});
frm.set_query("income_account", "items", function() {
return{
query: "erpnext.controllers.queries.get_income_account",
filters: {
'company': frm.doc.company,
"disabled": 0
}
}
});
frm.custom_make_buttons = {
'Delivery Note': 'Delivery',
'Sales Invoice': 'Return / Credit Note',

View File

@ -110,6 +110,11 @@ frappe.query_reports["Accounts Payable Summary"] = {
"fieldname":"based_on_payment_terms",
"label": __("Based On Payment Terms"),
"fieldtype": "Check",
},
{
"fieldname": "for_revaluation_journals",
"label": __("Revaluation Journals"),
"fieldtype": "Check",
}
],

View File

@ -114,10 +114,13 @@ frappe.query_reports["Accounts Receivable"] = {
"reqd": 1
},
{
"fieldname": "customer_group",
"fieldname":"customer_group",
"label": __("Customer Group"),
"fieldtype": "Link",
"options": "Customer Group"
"fieldtype": "MultiSelectList",
"options": "Customer Group",
get_data: function(txt) {
return frappe.db.get_link_options('Customer Group', txt);
}
},
{
"fieldname": "payment_terms_template",
@ -173,12 +176,18 @@ frappe.query_reports["Accounts Receivable"] = {
"label": __("Show Remarks"),
"fieldtype": "Check",
},
{
"fieldname": "for_revaluation_journals",
"label": __("Revaluation Journals"),
"fieldtype": "Check",
},
{
"fieldname": "ignore_accounts",
"label": __("Group by Voucher"),
"fieldtype": "Check",
}
],
"formatter": function(value, row, column, data, default_formatter) {

View File

@ -14,7 +14,7 @@ from erpnext.accounts.doctype.accounting_dimension.accounting_dimension import (
get_accounting_dimensions,
get_dimension_with_children,
)
from erpnext.accounts.utils import get_currency_precision
from erpnext.accounts.utils import get_currency_precision, get_party_types_from_account_type
# This report gives a summary of all Outstanding Invoices considering the following
@ -72,9 +72,7 @@ class ReceivablePayableReport(object):
self.currency_precision = get_currency_precision() or 2
self.dr_or_cr = "debit" if self.filters.account_type == "Receivable" else "credit"
self.account_type = self.filters.account_type
self.party_type = frappe.db.get_all(
"Party Type", {"account_type": self.account_type}, pluck="name"
)
self.party_type = get_party_types_from_account_type(self.account_type)
self.party_details = {}
self.invoices = set()
self.skip_total_row = 0
@ -281,11 +279,20 @@ class ReceivablePayableReport(object):
row.invoice_grand_total = row.invoiced
if (abs(row.outstanding) > 1.0 / 10**self.currency_precision) and (
(abs(row.outstanding_in_account_currency) > 1.0 / 10**self.currency_precision)
or (row.voucher_no in self.err_journals)
):
must_consider = False
if self.filters.get("for_revaluation_journals"):
if (abs(row.outstanding) > 1.0 / 10**self.currency_precision) or (
(abs(row.outstanding_in_account_currency) > 1.0 / 10**self.currency_precision)
):
must_consider = True
else:
if (abs(row.outstanding) > 1.0 / 10**self.currency_precision) and (
(abs(row.outstanding_in_account_currency) > 1.0 / 10**self.currency_precision)
or (row.voucher_no in self.err_journals)
):
must_consider = True
if must_consider:
# non-zero oustanding, we must consider this row
if self.is_invoice(row) and self.filters.based_on_payment_terms:
@ -840,7 +847,13 @@ class ReceivablePayableReport(object):
self.customer = qb.DocType("Customer")
if self.filters.get("customer_group"):
self.get_hierarchical_filters("Customer Group", "customer_group")
groups = get_customer_group_with_children(self.filters.customer_group)
customers = (
qb.from_(self.customer)
.select(self.customer.name)
.where(self.customer["customer_group"].isin(groups))
)
self.qb_selection_filter.append(self.ple.party.isin(customers))
if self.filters.get("territory"):
self.get_hierarchical_filters("Territory", "territory")
@ -1132,3 +1145,19 @@ class ReceivablePayableReport(object):
.run()
)
self.err_journals = [x[0] for x in results] if results else []
def get_customer_group_with_children(customer_groups):
if not isinstance(customer_groups, list):
customer_groups = [d.strip() for d in customer_groups.strip().split(",") if d]
all_customer_groups = []
for d in customer_groups:
if frappe.db.exists("Customer Group", d):
lft, rgt = frappe.db.get_value("Customer Group", d, ["lft", "rgt"])
children = frappe.get_all("Customer Group", filters={"lft": [">=", lft], "rgt": ["<=", rgt]})
all_customer_groups += [c.name for c in children]
else:
frappe.throw(_("Customer Group: {0} does not exist").format(d))
return list(set(all_customer_groups))

View File

@ -475,6 +475,30 @@ class TestAccountsReceivable(AccountsTestMixin, FrappeTestCase):
report = execute(filters)[1]
self.assertEqual(len(report), 0)
def test_multi_customer_group_filter(self):
si = self.create_sales_invoice()
cus_group = frappe.db.get_value("Customer", self.customer, "customer_group")
# Create a list of customer groups, e.g., ["Group1", "Group2"]
cus_groups_list = [cus_group, "_Test Customer Group 1"]
filters = {
"company": self.company,
"report_date": today(),
"range1": 30,
"range2": 60,
"range3": 90,
"range4": 120,
"customer_group": cus_groups_list, # Use the list of customer groups
}
report = execute(filters)[1]
# Assert that the report contains data for the specified customer groups
self.assertTrue(len(report) > 0)
for row in report:
# Assert that the customer group of each row is in the list of customer groups
self.assertIn(row.customer_group, cus_groups_list)
def test_party_account_filter(self):
si1 = self.create_sales_invoice()
self.customer2 = (

View File

@ -139,6 +139,11 @@ frappe.query_reports["Accounts Receivable Summary"] = {
"label": __("Show GL Balance"),
"fieldtype": "Check",
},
{
"fieldname": "for_revaluation_journals",
"label": __("Revaluation Journals"),
"fieldtype": "Check",
}
],
onload: function(report) {

View File

@ -8,6 +8,7 @@ from frappe.utils import cint, flt
from erpnext.accounts.party import get_partywise_advanced_payment_amount
from erpnext.accounts.report.accounts_receivable.accounts_receivable import ReceivablePayableReport
from erpnext.accounts.utils import get_party_types_from_account_type
def execute(filters=None):
@ -22,9 +23,7 @@ def execute(filters=None):
class AccountsReceivableSummary(ReceivablePayableReport):
def run(self, args):
self.account_type = args.get("account_type")
self.party_type = frappe.db.get_all(
"Party Type", {"account_type": self.account_type}, pluck="name"
)
self.party_type = get_party_types_from_account_type(self.account_type)
self.party_naming_by = frappe.db.get_value(
args.get("naming_by")[0], None, args.get("naming_by")[1]
)

View File

@ -31,6 +31,18 @@ frappe.query_reports["Asset Depreciation Ledger"] = {
"fieldtype": "Link",
"options": "Asset"
},
{
"fieldname":"asset_category",
"label": __("Asset Category"),
"fieldtype": "Link",
"options": "Asset Category"
},
{
"fieldname":"cost_center",
"label": __("Cost Center"),
"fieldtype": "Link",
"options": "Cost Center"
},
{
"fieldname":"finance_book",
"label": __("Finance Book"),
@ -38,10 +50,10 @@ frappe.query_reports["Asset Depreciation Ledger"] = {
"options": "Finance Book"
},
{
"fieldname":"asset_category",
"label": __("Asset Category"),
"fieldtype": "Link",
"options": "Asset Category"
}
"fieldname": "include_default_book_assets",
"label": __("Include Default FB Assets"),
"fieldtype": "Check",
"default": 1
},
]
}

View File

@ -1,15 +1,15 @@
{
"add_total_row": 1,
"add_total_row": 0,
"columns": [],
"creation": "2016-04-08 14:49:58.133098",
"disabled": 0,
"docstatus": 0,
"doctype": "Report",
"filters": [],
"idx": 2,
"idx": 6,
"is_standard": "Yes",
"letterhead": null,
"modified": "2023-07-26 21:05:33.554778",
"modified": "2023-11-08 20:17:05.774211",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Asset Depreciation Ledger",

View File

@ -4,7 +4,7 @@
import frappe
from frappe import _
from frappe.utils import flt
from frappe.utils import cstr, flt
def execute(filters=None):
@ -32,7 +32,6 @@ def get_data(filters):
filters_data.append(["against_voucher", "=", filters.get("asset")])
if filters.get("asset_category"):
assets = frappe.db.sql_list(
"""select name from tabAsset
where asset_category = %s and docstatus=1""",
@ -41,12 +40,27 @@ def get_data(filters):
filters_data.append(["against_voucher", "in", assets])
if filters.get("finance_book"):
filters_data.append(["finance_book", "in", ["", filters.get("finance_book")]])
company_fb = frappe.get_cached_value("Company", filters.get("company"), "default_finance_book")
if filters.get("include_default_book_assets") and company_fb:
if filters.get("finance_book") and cstr(filters.get("finance_book")) != cstr(company_fb):
frappe.throw(_("To use a different finance book, please uncheck 'Include Default FB Assets'"))
else:
finance_book = company_fb
elif filters.get("finance_book"):
finance_book = filters.get("finance_book")
else:
finance_book = None
if finance_book:
or_filters_data = [["finance_book", "in", ["", finance_book]], ["finance_book", "is", "not set"]]
else:
or_filters_data = [["finance_book", "in", [""]], ["finance_book", "is", "not set"]]
gl_entries = frappe.get_all(
"GL Entry",
filters=filters_data,
or_filters=or_filters_data,
fields=["against_voucher", "debit_in_account_currency as debit", "voucher_no", "posting_date"],
order_by="against_voucher, posting_date",
)
@ -61,7 +75,9 @@ def get_data(filters):
asset_data = assets_details.get(d.against_voucher)
if asset_data:
if not asset_data.get("accumulated_depreciation_amount"):
asset_data.accumulated_depreciation_amount = d.debit
asset_data.accumulated_depreciation_amount = d.debit + asset_data.get(
"opening_accumulated_depreciation"
)
else:
asset_data.accumulated_depreciation_amount += d.debit
@ -70,7 +86,7 @@ def get_data(filters):
{
"depreciation_amount": d.debit,
"depreciation_date": d.posting_date,
"amount_after_depreciation": (
"value_after_depreciation": (
flt(row.gross_purchase_amount) - flt(row.accumulated_depreciation_amount)
),
"depreciation_entry": d.voucher_no,
@ -88,10 +104,12 @@ def get_assets_details(assets):
fields = [
"name as asset",
"gross_purchase_amount",
"opening_accumulated_depreciation",
"asset_category",
"status",
"depreciation_method",
"purchase_date",
"cost_center",
]
for d in frappe.get_all("Asset", fields=fields, filters={"name": ("in", assets)}):
@ -121,6 +139,12 @@ def get_columns():
"fieldtype": "Currency",
"width": 120,
},
{
"label": _("Opening Accumulated Depreciation"),
"fieldname": "opening_accumulated_depreciation",
"fieldtype": "Currency",
"width": 140,
},
{
"label": _("Depreciation Amount"),
"fieldname": "depreciation_amount",
@ -134,8 +158,8 @@ def get_columns():
"width": 210,
},
{
"label": _("Amount After Depreciation"),
"fieldname": "amount_after_depreciation",
"label": _("Value After Depreciation"),
"fieldname": "value_after_depreciation",
"fieldtype": "Currency",
"width": 180,
},
@ -153,12 +177,13 @@ def get_columns():
"options": "Asset Category",
"width": 120,
},
{"label": _("Current Status"), "fieldname": "status", "fieldtype": "Data", "width": 120},
{
"label": _("Depreciation Method"),
"fieldname": "depreciation_method",
"fieldtype": "Data",
"width": 130,
"label": _("Cost Center"),
"fieldtype": "Link",
"fieldname": "cost_center",
"options": "Cost Center",
"width": 100,
},
{"label": _("Current Status"), "fieldname": "status", "fieldtype": "Data", "width": 120},
{"label": _("Purchase Date"), "fieldname": "purchase_date", "fieldtype": "Date", "width": 120},
]

View File

@ -17,7 +17,7 @@ frappe.query_reports["Balance Sheet"]["filters"].push({
frappe.query_reports["Balance Sheet"]["filters"].push({
fieldname: "include_default_book_entries",
label: __("Include Default Book Entries"),
label: __("Include Default FB Entries"),
fieldtype: "Check",
default: 1,
});

View File

@ -17,7 +17,7 @@ frappe.query_reports["Cash Flow"]["filters"].splice(8, 1);
frappe.query_reports["Cash Flow"]["filters"].push(
{
"fieldname": "include_default_book_entries",
"label": __("Include Default Book Entries"),
"label": __("Include Default FB Entries"),
"fieldtype": "Check",
"default": 1
}

View File

@ -104,7 +104,7 @@ frappe.query_reports["Consolidated Financial Statement"] = {
},
{
"fieldname": "include_default_book_entries",
"label": __("Include Default Book Entries"),
"label": __("Include Default FB Entries"),
"fieldtype": "Check",
"default": 1
},

View File

@ -561,9 +561,7 @@ def apply_additional_conditions(doctype, query, from_date, ignore_closing_entrie
company_fb = frappe.get_cached_value("Company", filters.company, "default_finance_book")
if filters.finance_book and company_fb and cstr(filters.finance_book) != cstr(company_fb):
frappe.throw(
_("To use a different finance book, please uncheck 'Include Default Book Entries'")
)
frappe.throw(_("To use a different finance book, please uncheck 'Include Default FB Entries'"))
query = query.where(
(gl_entry.finance_book.isin([cstr(filters.finance_book), cstr(company_fb), ""]))

View File

@ -175,7 +175,7 @@ frappe.query_reports["General Ledger"] = {
},
{
"fieldname": "include_default_book_entries",
"label": __("Include Default Book Entries"),
"label": __("Include Default FB Entries"),
"fieldtype": "Check",
"default": 1
},

View File

@ -259,9 +259,7 @@ def get_conditions(filters):
if filters.get("company_fb") and cstr(filters.get("finance_book")) != cstr(
filters.get("company_fb")
):
frappe.throw(
_("To use a different finance book, please uncheck 'Include Default Book Entries'")
)
frappe.throw(_("To use a different finance book, please uncheck 'Include Default FB Entries'"))
else:
conditions.append("(finance_book in (%(finance_book)s, '') OR finance_book IS NULL)")
else:

View File

@ -316,7 +316,7 @@ 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",
title=_("Accounts Missing Error"),
)
gle = frappe.qb.DocType("GL Entry")
query = (

View File

@ -95,7 +95,7 @@ frappe.query_reports["Trial Balance"] = {
},
{
"fieldname": "include_default_book_entries",
"label": __("Include Default Book Entries"),
"label": __("Include Default FB Entries"),
"fieldtype": "Check",
"default": 1
},

View File

@ -275,9 +275,7 @@ def get_opening_balance(
company_fb = frappe.get_cached_value("Company", filters.company, "default_finance_book")
if filters.finance_book and company_fb and cstr(filters.finance_book) != cstr(company_fb):
frappe.throw(
_("To use a different finance book, please uncheck 'Include Default Book Entries'")
)
frappe.throw(_("To use a different finance book, please uncheck 'Include Default FB Entries'"))
opening_balance = opening_balance.where(
(closing_balance.finance_book.isin([cstr(filters.finance_book), cstr(company_fb), ""]))

View File

@ -2040,3 +2040,7 @@ def create_gain_loss_journal(
journal_entry.save()
journal_entry.submit()
return journal_entry.name
def get_party_types_from_account_type(account_type):
return frappe.db.get_all("Party Type", {"account_type": account_type}, pluck="name")

View File

@ -52,7 +52,7 @@ frappe.query_reports["Fixed Asset Register"] = {
},
{
"fieldname": "include_default_book_assets",
"label": __("Include Default Book Assets"),
"label": __("Include Default FB Assets"),
"fieldtype": "Check",
"default": 1
},

View File

@ -223,7 +223,7 @@ def get_assets_linked_to_fb(filters):
company_fb = frappe.get_cached_value("Company", filters.company, "default_finance_book")
if filters.finance_book and company_fb and cstr(filters.finance_book) != cstr(company_fb):
frappe.throw(_("To use a different finance book, please uncheck 'Include Default Book Assets'"))
frappe.throw(_("To use a different finance book, please uncheck 'Include Default FB Assets'"))
query = query.where(
(afb.finance_book.isin([cstr(filters.finance_book), cstr(company_fb), ""]))

View File

@ -365,7 +365,7 @@ class BuyingController(SubcontractingController):
{
"item_code": d.item_code,
"warehouse": d.get("from_warehouse"),
"posting_date": self.get("posting_date") or self.get("transation_date"),
"posting_date": self.get("posting_date") or self.get("transaction_date"),
"posting_time": posting_time,
"qty": -1 * flt(d.get("stock_qty")),
"serial_and_batch_bundle": d.get("serial_and_batch_bundle"),

View File

@ -611,6 +611,8 @@ def get_income_account(doctype, txt, searchfield, start, page_len, filters):
if filters.get("company"):
condition += "and tabAccount.company = %(company)s"
condition += f"and tabAccount.disabled = {filters.get('disabled', 0)}"
return frappe.db.sql(
"""select tabAccount.name from `tabAccount`
where (tabAccount.report_type = "Profit and Loss"

View File

@ -89,10 +89,6 @@ frappe.ui.form.on('Production Plan', {
frm.trigger("show_progress");
if (frm.doc.status !== "Completed") {
frm.add_custom_button(__("Work Order Tree"), ()=> {
frappe.set_route('Tree', 'Work Order', {production_plan: frm.doc.name});
}, __('View'));
frm.add_custom_button(__("Production Plan Summary"), ()=> {
frappe.set_route('query-report', 'Production Plan Summary', {production_plan: frm.doc.name});
}, __('View'));

View File

@ -828,8 +828,6 @@ class ProductionPlan(Document):
# Combine subassembly items
sub_assembly_items_store = self.combine_subassembly_items(sub_assembly_items_store)
sub_assembly_items_store.sort(key=lambda d: d.bom_level, reverse=True) # sort by bom level
for idx, row in enumerate(sub_assembly_items_store):
row.idx = idx + 1
self.append("sub_assembly_items", row)

View File

@ -664,49 +664,6 @@ class TestProductionPlan(FrappeTestCase):
frappe.db.rollback()
def test_subassmebly_sorting(self):
"Test subassembly sorting in case of multiple items with nested BOMs."
from erpnext.manufacturing.doctype.bom.test_bom import create_nested_bom
prefix = "_TestLevel_"
boms = {
"Assembly": {
"SubAssembly1": {
"ChildPart1": {},
"ChildPart2": {},
},
"ChildPart6": {},
"SubAssembly4": {"SubSubAssy2": {"ChildPart7": {}}},
},
"MegaDeepAssy": {
"SecretSubassy": {
"SecretPart": {"VerySecret": {"SuperSecret": {"Classified": {}}}},
},
# ^ assert that this is
# first item in subassy table
},
}
create_nested_bom(boms, prefix=prefix)
items = [prefix + item_code for item_code in boms.keys()]
plan = create_production_plan(item_code=items[0], do_not_save=True)
plan.append(
"po_items",
{
"use_multi_level_bom": 1,
"item_code": items[1],
"bom_no": frappe.db.get_value("Item", items[1], "default_bom"),
"planned_qty": 1,
"planned_start_date": now_datetime(),
},
)
plan.get_sub_assembly_items()
bom_level_order = [d.bom_level for d in plan.sub_assembly_items]
self.assertEqual(bom_level_order, sorted(bom_level_order, reverse=True))
# lowest most level of subassembly should be first
self.assertIn("SuperSecret", plan.sub_assembly_items[0].production_item)
def test_multiple_work_order_for_production_plan_item(self):
"Test producing Prod Plan (making WO) in parts."

View File

@ -22,9 +22,9 @@ frappe.query_reports["Production Plan Summary"] = {
"formatter": function(value, row, column, data, default_formatter) {
value = default_formatter(value, row, column, data);
if (column.fieldname == "document_name") {
if (column.fieldname == "item_code") {
var color = data.pending_qty > 0 ? 'red': 'green';
value = `<a style='color:${color}' href="#Form/${data['document_type']}/${data['document_name']}" data-doctype="${data['document_type']}">${data['document_name']}</a>`;
value = `<a style='color:${color}' href="/app/item/${data['item_code']}" data-doctype="Item">${data['item_code']}</a>`;
}
return value;

View File

@ -44,6 +44,7 @@ def get_production_plan_item_details(filters, data, order_details):
{
"indent": 0,
"item_code": row.item_code,
"sales_order": row.get("sales_order"),
"item_name": frappe.get_cached_value("Item", row.item_code, "item_name"),
"qty": row.planned_qty,
"document_type": "Work Order",
@ -80,7 +81,7 @@ def get_production_plan_sub_assembly_item_details(
data.append(
{
"indent": 1,
"indent": 1 + item.indent,
"item_code": item.production_item,
"item_name": item.item_name,
"qty": item.qty,
@ -98,7 +99,7 @@ def get_work_order_details(filters, order_details):
for row in frappe.get_all(
"Work Order",
filters={"production_plan": filters.get("production_plan")},
fields=["name", "produced_qty", "production_plan", "production_item"],
fields=["name", "produced_qty", "production_plan", "production_item", "sales_order"],
):
order_details.setdefault((row.name, row.production_item), row)
@ -118,10 +119,17 @@ def get_column(filters):
"label": _("Finished Good"),
"fieldtype": "Link",
"fieldname": "item_code",
"width": 300,
"width": 240,
"options": "Item",
},
{"label": _("Item Name"), "fieldtype": "data", "fieldname": "item_name", "width": 100},
{"label": _("Item Name"), "fieldtype": "data", "fieldname": "item_name", "width": 150},
{
"label": _("Sales Order"),
"options": "Sales Order",
"fieldtype": "Link",
"fieldname": "sales_order",
"width": 100,
},
{
"label": _("Document Type"),
"fieldtype": "Link",
@ -133,10 +141,16 @@ def get_column(filters):
"label": _("Document Name"),
"fieldtype": "Dynamic Link",
"fieldname": "document_name",
"width": 150,
"options": "document_type",
"width": 180,
},
{"label": _("BOM Level"), "fieldtype": "Int", "fieldname": "bom_level", "width": 100},
{"label": _("Order Qty"), "fieldtype": "Float", "fieldname": "qty", "width": 120},
{"label": _("Received Qty"), "fieldtype": "Float", "fieldname": "produced_qty", "width": 160},
{
"label": _("Produced / Received Qty"),
"fieldtype": "Float",
"fieldname": "produced_qty",
"width": 200,
},
{"label": _("Pending Qty"), "fieldtype": "Float", "fieldname": "pending_qty", "width": 110},
]

View File

@ -15,6 +15,7 @@ from frappe.model.mapper import get_mapped_doc
from frappe.model.naming import set_name_by_naming_series, set_name_from_naming_options
from frappe.model.utils.rename_doc import update_linked_doctypes
from frappe.utils import cint, cstr, flt, get_formatted_email, today
from frappe.utils.deprecations import deprecated
from frappe.utils.user import get_users_with_role
from erpnext.accounts.party import get_dashboard_info, validate_party_accounts # noqa
@ -303,20 +304,22 @@ class Customer(TransactionBase):
)
@deprecated
def create_contact(contact, party_type, party, email):
"""Create contact based on given contact name"""
contact = contact.split(" ")
contact = frappe.get_doc(
first, middle, last = parse_full_name(contact)
doc = frappe.get_doc(
{
"doctype": "Contact",
"first_name": contact[0],
"last_name": len(contact) > 1 and contact[1] or "",
"first_name": first,
"middle_name": middle,
"last_name": last,
"is_primary_contact": 1,
}
)
contact.append("email_ids", dict(email_id=email, is_primary=1))
contact.append("links", dict(link_doctype=party_type, link_name=party))
contact.insert()
doc.append("email_ids", dict(email_id=email, is_primary=1))
doc.append("links", dict(link_doctype=party_type, link_name=party))
return doc.insert()
@frappe.whitelist()
@ -495,6 +498,7 @@ def check_credit_limit(customer, company, ignore_outstanding_sales_order=False,
primary_action={
"label": "Send Email",
"server_action": "erpnext.selling.doctype.customer.customer.send_emails",
"hide_on_success": True,
"args": {
"customer": customer,
"customer_outstanding": customer_outstanding,
@ -635,24 +639,42 @@ def get_credit_limit(customer, company):
def make_contact(args, is_primary_contact=1):
contact = frappe.get_doc(
{
"doctype": "Contact",
"first_name": args.get("name"),
"is_primary_contact": is_primary_contact,
"links": [{"link_doctype": args.get("doctype"), "link_name": args.get("name")}],
}
)
values = {
"doctype": "Contact",
"is_primary_contact": is_primary_contact,
"links": [{"link_doctype": args.get("doctype"), "link_name": args.get("name")}],
}
if args.customer_type == "Individual":
first, middle, last = parse_full_name(args.get("customer_name"))
values.update(
{
"first_name": first,
"middle_name": middle,
"last_name": last,
}
)
else:
values.update(
{
"company_name": args.get("customer_name"),
}
)
contact = frappe.get_doc(values)
if args.get("email_id"):
contact.add_email(args.get("email_id"), is_primary=True)
if args.get("mobile_no"):
contact.add_phone(args.get("mobile_no"), is_primary_mobile_no=True)
contact.insert()
if flags := args.get("flags"):
contact.insert(ignore_permissions=flags.get("ignore_permissions"))
else:
contact.insert()
return contact
def make_address(args, is_primary_address=1):
def make_address(args, is_primary_address=1, is_shipping_address=1):
reqd_fields = []
for field in ["city", "country"]:
if not args.get(field):
@ -668,16 +690,23 @@ def make_address(args, is_primary_address=1):
address = frappe.get_doc(
{
"doctype": "Address",
"address_title": args.get("name"),
"address_title": args.get("customer_name"),
"address_line1": args.get("address_line1"),
"address_line2": args.get("address_line2"),
"city": args.get("city"),
"state": args.get("state"),
"pincode": args.get("pincode"),
"country": args.get("country"),
"is_primary_address": is_primary_address,
"is_shipping_address": is_shipping_address,
"links": [{"link_doctype": args.get("doctype"), "link_name": args.get("name")}],
}
).insert()
)
if flags := args.get("flags"):
address.insert(ignore_permissions=flags.get("ignore_permissions"))
else:
address.insert()
return address
@ -698,3 +727,13 @@ def get_customer_primary_contact(doctype, txt, searchfield, start, page_len, fil
.where((dlink.link_name == customer) & (con.name.like(f"%{txt}%")))
.run()
)
def parse_full_name(full_name: str) -> tuple[str, str | None, str | None]:
"""Parse full name into first name, middle name and last name"""
names = full_name.split()
first_name = names[0]
middle_name = " ".join(names[1:-1]) if len(names) > 2 else None
last_name = names[-1] if len(names) > 1 else None
return first_name, middle_name, last_name

View File

@ -10,7 +10,11 @@ from frappe.utils import flt
from erpnext.accounts.party import get_due_date
from erpnext.exceptions import PartyDisabled, PartyFrozen
from erpnext.selling.doctype.customer.customer import get_credit_limit, get_customer_outstanding
from erpnext.selling.doctype.customer.customer import (
get_credit_limit,
get_customer_outstanding,
parse_full_name,
)
from erpnext.tests.utils import create_test_contact_and_address
test_ignore = ["Price List"]
@ -373,6 +377,22 @@ class TestCustomer(FrappeTestCase):
frappe.db.set_single_value("Selling Settings", "cust_master_name", "Customer Name")
def test_parse_full_name(self):
first, middle, last = parse_full_name("John")
self.assertEqual(first, "John")
self.assertEqual(middle, None)
self.assertEqual(last, None)
first, middle, last = parse_full_name("John Doe")
self.assertEqual(first, "John")
self.assertEqual(middle, None)
self.assertEqual(last, "Doe")
first, middle, last = parse_full_name("John Michael Doe")
self.assertEqual(first, "John")
self.assertEqual(middle, "Michael")
self.assertEqual(last, "Doe")
def get_customer_dict(customer_name):
return {

View File

@ -601,11 +601,12 @@ erpnext.PointOfSale.Controller = class {
// if item is clicked twice from item selector
// then "item_code, batch_no, uom, rate" will help in getting the exact item
// to increase the qty by one
const has_batch_no = batch_no;
const has_batch_no = (batch_no !== 'null' && batch_no !== null);
item_row = this.frm.doc.items.find(
i => i.item_code === item_code
&& (!has_batch_no || (has_batch_no && i.batch_no === batch_no))
&& (i.uom === uom)
&& (i.rate === flt(rate))
);
}

View File

@ -80,7 +80,7 @@ def get_data(filters=None):
territory_orders = []
if t_quotation_names and sales_orders:
list(filter(lambda x: x.quotation in t_quotation_names, sales_orders))
territory_orders = list(filter(lambda x: x.quotation in t_quotation_names, sales_orders))
t_order_names = []
if territory_orders:
t_order_names = [t.name for t in territory_orders]

View File

@ -108,7 +108,16 @@ class TransactionDeletionRecord(Document):
if no_of_docs > 0:
self.delete_version_log(docfield["parent"], docfield["fieldname"])
self.delete_communications(docfield["parent"], docfield["fieldname"])
reference_docs = frappe.get_all(
docfield["parent"], filters={docfield["fieldname"]: self.company}
)
reference_doc_names = [r.name for r in reference_docs]
self.delete_communications(docfield["parent"], reference_doc_names)
self.delete_comments(docfield["parent"], reference_doc_names)
self.unlink_attachments(docfield["parent"], reference_doc_names)
self.populate_doctypes_table(tables, docfield["parent"], no_of_docs)
self.delete_child_tables(docfield["parent"], docfield["fieldname"])
@ -197,19 +206,49 @@ class TransactionDeletionRecord(Document):
(versions.ref_doctype == doctype) & (versions.docname.isin(batch))
).run()
def delete_communications(self, doctype, company_fieldname):
reference_docs = frappe.get_all(doctype, filters={company_fieldname: self.company})
reference_doc_names = [r.name for r in reference_docs]
def delete_communications(self, doctype, reference_doc_names):
communications = frappe.get_all(
"Communication",
filters={"reference_doctype": doctype, "reference_name": ["in", reference_doc_names]},
)
communication_names = [c.name for c in communications]
if not communication_names:
return
for batch in create_batch(communication_names, self.batch_size):
frappe.delete_doc("Communication", batch, ignore_permissions=True)
def delete_comments(self, doctype, reference_doc_names):
comments = frappe.get_all(
"Comment",
filters={"reference_doctype": doctype, "reference_name": ["in", reference_doc_names]},
)
comment_names = [c.name for c in comments]
if not comment_names:
return
for batch in create_batch(comment_names, self.batch_size):
frappe.delete_doc("Comment", batch, ignore_permissions=True)
def unlink_attachments(self, doctype, reference_doc_names):
files = frappe.get_all(
"File",
filters={"attached_to_doctype": doctype, "attached_to_name": ["in", reference_doc_names]},
)
file_names = [c.name for c in files]
if not file_names:
return
file = qb.DocType("File")
for batch in create_batch(file_names, self.batch_size):
qb.update(file).set(file.attached_to_doctype, None).set(file.attached_to_name, None).where(
file.name.isin(batch)
).run()
@frappe.whitelist()
def get_doctypes_to_be_ignored():

View File

@ -61,6 +61,7 @@
"oldfieldname": "item",
"oldfieldtype": "Link",
"options": "Item",
"read_only_depends_on": "eval:!doc.__islocal",
"reqd": 1
},
{
@ -207,7 +208,7 @@
"image_field": "image",
"links": [],
"max_attachments": 5,
"modified": "2023-03-12 15:56:09.516586",
"modified": "2023-11-09 12:17:28.339975",
"modified_by": "Administrator",
"module": "Stock",
"name": "Batch",

View File

@ -7,7 +7,7 @@ from frappe import _, throw
from frappe.desk.notifications import clear_doctype_notifications
from frappe.model.mapper import get_mapped_doc
from frappe.query_builder.functions import CombineDatetime
from frappe.utils import cint, flt, getdate, nowdate
from frappe.utils import cint, flt, get_datetime, getdate, nowdate
from pypika import functions as fn
import erpnext
@ -829,8 +829,12 @@ class PurchaseReceipt(BuyingController):
update_billing_percentage(pr_doc, update_modified=update_modified)
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")
if (
self.is_return
or not frappe.db.get_single_value("Stock Settings", "enable_stock_reservation")
or not frappe.db.get_single_value(
"Stock Settings", "auto_reserve_stock_for_sales_order_on_purchase"
)
):
return
@ -851,6 +855,11 @@ class PurchaseReceipt(BuyingController):
so_items_details_map.setdefault(item.sales_order, []).append(item_details)
if so_items_details_map:
if get_datetime("{} {}".format(self.posting_date, self.posting_time)) > get_datetime():
return frappe.msgprint(
_("Cannot create Stock Reservation Entries for future dated Purchase Receipts.")
)
for so, items_details in so_items_details_map.items():
so_doc = frappe.get_doc("Sales Order", so)
so_doc.create_stock_reservation_entries(

View File

@ -1599,6 +1599,9 @@ def get_ledgers_from_serial_batch_bundle(**kwargs) -> List[frappe._dict]:
)
for key, val in kwargs.items():
if not val:
continue
if key in ["get_subcontracted_item"]:
continue

View File

@ -11,6 +11,7 @@
"warehouse",
"posting_date",
"posting_time",
"is_adjustment_entry",
"column_break_6",
"voucher_type",
"voucher_no",
@ -333,6 +334,12 @@
"fieldname": "has_serial_no",
"fieldtype": "Check",
"label": "Has Serial No"
},
{
"default": "0",
"fieldname": "is_adjustment_entry",
"fieldtype": "Check",
"label": "Is Adjustment Entry"
}
],
"hide_toolbar": 1,
@ -341,7 +348,7 @@
"in_create": 1,
"index_web_pages_for_search": 1,
"links": [],
"modified": "2023-04-03 16:33:16.270722",
"modified": "2023-10-23 18:07:42.063615",
"modified_by": "Administrator",
"module": "Stock",
"name": "Stock Ledger Entry",

View File

@ -413,6 +413,11 @@ class StockReconciliation(StockController):
sl_entries = []
for row in self.items:
if not row.qty and not row.valuation_rate and not row.current_qty:
self.make_adjustment_entry(row, sl_entries)
continue
item = frappe.get_cached_value(
"Item", row.item_code, ["has_serial_no", "has_batch_no"], as_dict=1
)
@ -463,6 +468,21 @@ class StockReconciliation(StockController):
)
self.make_sl_entries(sl_entries, allow_negative_stock=allow_negative_stock)
def make_adjustment_entry(self, row, sl_entries):
from erpnext.stock.stock_ledger import get_stock_value_difference
difference_amount = get_stock_value_difference(
row.item_code, row.warehouse, self.posting_date, self.posting_time
)
if not difference_amount:
return
args = self.get_sle_for_items(row)
args.update({"stock_value_difference": -1 * difference_amount, "is_adjustment_entry": 1})
sl_entries.append(args)
def get_sle_for_serialized_items(self, row, sl_entries):
if row.current_serial_and_batch_bundle:
args = self.get_sle_for_items(row)

View File

@ -752,9 +752,11 @@ class update_entries_after(object):
sle.valuation_rate = self.wh_data.valuation_rate
sle.stock_value = self.wh_data.stock_value
sle.stock_queue = json.dumps(self.wh_data.stock_queue)
sle.stock_value_difference = stock_value_difference
sle.doctype = "Stock Ledger Entry"
if not sle.is_adjustment_entry or not self.args.get("sle_id"):
sle.stock_value_difference = stock_value_difference
sle.doctype = "Stock Ledger Entry"
frappe.get_doc(sle).db_update()
if not self.args.get("sle_id"):
@ -1929,3 +1931,27 @@ def is_internal_transfer(sle):
if data.is_internal_supplier and data.represents_company == data.company:
return True
def get_stock_value_difference(item_code, warehouse, posting_date, posting_time, voucher_no=None):
table = frappe.qb.DocType("Stock Ledger Entry")
query = (
frappe.qb.from_(table)
.select(Sum(table.stock_value_difference).as_("value"))
.where(
(table.is_cancelled == 0)
& (table.item_code == item_code)
& (table.warehouse == warehouse)
& (
(table.posting_date < posting_date)
| ((table.posting_date == posting_date) & (table.posting_time <= posting_time))
)
)
)
if voucher_no:
query = query.where(table.voucher_no != voucher_no)
difference_amount = query.run()
return flt(difference_amount[0][0]) if difference_amount else 0

View File

@ -148,6 +148,8 @@ class SubcontractingReceipt(SubcontractingController):
if (
frappe.db.get_single_value("Buying Settings", "backflush_raw_materials_of_subcontract_based_on")
== "BOM"
and self.supplied_items
and not any(item.serial_and_batch_bundle for item in self.supplied_items)
):
self.supplied_items = []

View File

@ -6,7 +6,7 @@ import copy
import frappe
from frappe.tests.utils import FrappeTestCase
from frappe.utils import add_days, cint, cstr, flt, today
from frappe.utils import add_days, cint, cstr, flt, nowtime, today
import erpnext
from erpnext.accounts.doctype.account.test_account import get_inventory_account
@ -26,6 +26,10 @@ from erpnext.controllers.tests.test_subcontracting_controller import (
from erpnext.manufacturing.doctype.production_plan.test_production_plan import make_bom
from erpnext.stock.doctype.item.test_item import make_item
from erpnext.stock.doctype.purchase_receipt.test_purchase_receipt import get_gl_entries
from erpnext.stock.doctype.serial_and_batch_bundle.test_serial_and_batch_bundle import (
get_batch_from_bundle,
make_serial_batch_bundle,
)
from erpnext.stock.doctype.stock_entry.test_stock_entry import make_stock_entry
from erpnext.stock.doctype.stock_reconciliation.test_stock_reconciliation import (
create_stock_reconciliation,
@ -507,6 +511,71 @@ class TestSubcontractingReceipt(FrappeTestCase):
self.assertNotEqual(scr.supplied_items[0].rate, prev_cost)
self.assertEqual(scr.supplied_items[0].rate, sr.items[0].valuation_rate)
def test_subcontracting_receipt_for_batch_raw_materials_without_material_transfer(self):
set_backflush_based_on("BOM")
fg_item = make_item(properties={"is_stock_item": 1, "is_sub_contracted_item": 1}).name
rm_item1 = make_item(
properties={
"is_stock_item": 1,
"has_batch_no": 1,
"create_new_batch": 1,
"batch_number_series": "BNGS-.####",
}
).name
bom = make_bom(item=fg_item, raw_materials=[rm_item1])
rm_batch_no = None
for row in bom.items:
se = make_stock_entry(
item_code=row.item_code,
qty=1,
target="_Test Warehouse 1 - _TC",
rate=300,
)
se.reload()
rm_batch_no = get_batch_from_bundle(se.items[0].serial_and_batch_bundle)
service_items = [
{
"warehouse": "_Test Warehouse - _TC",
"item_code": "Subcontracted Service Item 1",
"qty": 1,
"rate": 100,
"fg_item": fg_item,
"fg_item_qty": 1,
},
]
sco = get_subcontracting_order(service_items=service_items)
scr = make_subcontracting_receipt(sco.name)
scr.save()
scr.reload()
bundle_doc = make_serial_batch_bundle(
{
"item_code": scr.supplied_items[0].rm_item_code,
"warehouse": "_Test Warehouse 1 - _TC",
"voucher_type": "Subcontracting Receipt",
"posting_date": today(),
"posting_time": nowtime(),
"qty": -1,
"batches": frappe._dict({rm_batch_no: 1}),
"type_of_transaction": "Outward",
"do_not_submit": True,
}
)
scr.supplied_items[0].serial_and_batch_bundle = bundle_doc.name
scr.submit()
scr.reload()
batch_no = get_batch_from_bundle(scr.supplied_items[0].serial_and_batch_bundle)
self.assertEqual(batch_no, rm_batch_no)
self.assertEqual(scr.items[0].rm_cost_per_qty, 300)
self.assertEqual(scr.items[0].service_cost_per_qty, 100)
def test_subcontracting_receipt_raw_material_rate(self):
# Step - 1: Set Backflush Based On as "BOM"
set_backflush_based_on("BOM")

View File

@ -1153,7 +1153,7 @@ In Value,In Waarde,
"In the case of multi-tier program, Customers will be auto assigned to the concerned tier as per their spent",In die geval van &#39;n multi-vlak program sal kliënte outomaties toegewys word aan die betrokke vlak volgens hul besteding,
Inactive,onaktiewe,
Incentives,aansporings,
Include Default Book Entries,Sluit standaardboekinskrywings in,
Include Default FB Entries,Sluit standaardboekinskrywings in,
Include Exploded Items,Sluit ontplofte items in,
Include POS Transactions,Sluit POS-transaksies in,
Include UOM,Sluit UOM in,

Can't render this file because it is too large.

View File

@ -1153,7 +1153,7 @@ In Value,እሴት ውስጥ,
"In the case of multi-tier program, Customers will be auto assigned to the concerned tier as per their spent","በባለብዙ ደረጃ መርሃግብር ሁኔታ, ደንበኞች በተጠቀሱት ወጪ መሰረት ለተሰጣቸው ደረጃ ደረጃ በራስ መተላለፍ ይኖራቸዋል",
Inactive,ገባሪ አይደለም,
Incentives,ማበረታቻዎች,
Include Default Book Entries,ነባሪ የመጽሐፍ ግቤቶችን አካትት።,
Include Default FB Entries,ነባሪ የመጽሐፍ ግቤቶችን አካትት።,
Include Exploded Items,የተበተኑ ንጥሎችን አካት,
Include POS Transactions,የ POS ሽግግሮችን አክል,
Include UOM,UOM አካት,

Can't render this file because it is too large.

View File

@ -1153,7 +1153,7 @@ In Value,القيمة القادمة,
"In the case of multi-tier program, Customers will be auto assigned to the concerned tier as per their spent",في حالة البرنامج متعدد المستويات ، سيتم تعيين العملاء تلقائيًا إلى الطبقة المعنية وفقًا للإنفاق,
Inactive,غير نشط,
Incentives,الحوافز,
Include Default Book Entries,تضمين إدخالات دفتر افتراضي,
Include Default FB Entries,تضمين إدخالات دفتر افتراضي,
Include Exploded Items,تشمل البنود المستبعدة,
Include POS Transactions,تشمل معاملات نقطه البيع,
Include UOM,تضمين UOM,

Can't render this file because it is too large.

View File

@ -1153,7 +1153,7 @@ In Value,В стойност,
"In the case of multi-tier program, Customers will be auto assigned to the concerned tier as per their spent","В случай на многостепенна програма, клиентите ще бъдат автоматично зададени на съответния подреждан по тяхна сметка",
Inactive,неактивен,
Incentives,Стимули,
Include Default Book Entries,Включете записи по подразбиране на книги,
Include Default FB Entries,Включете записи по подразбиране на книги,
Include Exploded Items,Включете експлодираните елементи,
Include POS Transactions,Включете POS транзакции,
Include UOM,Включете UOM,

Can't render this file because it is too large.

View File

@ -1153,7 +1153,7 @@ In Value,মান,
"In the case of multi-tier program, Customers will be auto assigned to the concerned tier as per their spent","মাল্টি-টিয়ার প্রোগ্রামের ক্ষেত্রে, গ্রাহকরা তাদের ব্যয় অনুযায়ী সংশ্লিষ্ট টায়ারে স্বয়ংক্রিয়ভাবে নিয়োগ পাবেন",
Inactive,নিষ্ক্রিয়,
Incentives,ইনসেনটিভ,
Include Default Book Entries,ডিফল্ট বুক এন্ট্রি অন্তর্ভুক্ত করুন,
Include Default FB Entries,ডিফল্ট বুক এন্ট্রি অন্তর্ভুক্ত করুন,
Include Exploded Items,বিস্ফোরিত আইটেম অন্তর্ভুক্ত করুন,
Include POS Transactions,পিওএস লেনদেন অন্তর্ভুক্ত করুন,
Include UOM,UOM অন্তর্ভুক্ত করুন,

Can't render this file because it is too large.

View File

@ -1153,7 +1153,7 @@ In Value,u vrijednost,
"In the case of multi-tier program, Customers will be auto assigned to the concerned tier as per their spent","U slučaju višeslojnog programa, Korisnici će automatski biti dodeljeni za dotičnu grupu po njihovom trošenju",
Inactive,Neaktivan,
Incentives,Poticaji,
Include Default Book Entries,Uključite zadane unose knjiga,
Include Default FB Entries,Uključite zadane unose knjiga,
Include Exploded Items,Uključite eksplodirane predmete,
Include POS Transactions,Uključite POS transakcije,
Include UOM,Uključite UOM,

Can't render this file because it is too large.

View File

@ -1153,7 +1153,7 @@ In Value,En valor,
"In the case of multi-tier program, Customers will be auto assigned to the concerned tier as per their spent","En el cas del programa de diversos nivells, els clients seran assignats automàticament al nivell corresponent segons el seu gastat",
Inactive,Inactiu,
Incentives,Incentius,
Include Default Book Entries,Inclou les entrades de llibres predeterminats,
Include Default FB Entries,Inclou les entrades de llibres predeterminats,
Include Exploded Items,Inclou articles explotats,
Include POS Transactions,Inclou transaccions de POS,
Include UOM,Inclou UOM,

Can't render this file because it is too large.

View File

@ -1153,7 +1153,7 @@ In Value,v Hodnota,
"In the case of multi-tier program, Customers will be auto assigned to the concerned tier as per their spent",V případě víceúrovňového programu budou zákazníci automaticky přiděleni danému vrstvě podle svých vynaložených nákladů,
Inactive,Neaktivní,
Incentives,Pobídky,
Include Default Book Entries,Zahrnout výchozí položky knihy,
Include Default FB Entries,Zahrnout výchozí položky knihy,
Include Exploded Items,Zahrnout výbušné položky,
Include POS Transactions,Zahrnout POS transakce,
Include UOM,Zahrnout UOM,

Can't render this file because it is too large.

View File

@ -1153,7 +1153,7 @@ In Value,I Value,
"In the case of multi-tier program, Customers will be auto assigned to the concerned tier as per their spent","I tilfælde af multi-tier program, vil kunder automatisk blive tildelt den pågældende tier som per deres brugt",
Inactive,inaktive,
Incentives,Incitamenter,
Include Default Book Entries,Inkluder standardbogsindlæg,
Include Default FB Entries,Inkluder standardbogsindlæg,
Include Exploded Items,Inkluder eksploderede elementer,
Include POS Transactions,Inkluder POS-transaktioner,
Include UOM,Inkluder UOM,

Can't render this file because it is too large.

View File

@ -1160,7 +1160,7 @@ In Value,Wert bei,
"In the case of multi-tier program, Customers will be auto assigned to the concerned tier as per their spent",Im Falle eines mehrstufigen Programms werden Kunden automatisch der betroffenen Ebene entsprechend ihrer Ausgaben zugewiesen,
Inactive,Inaktiv,
Incentives,Anreize,
Include Default Book Entries,Standardbucheinträge einschließen,
Include Default FB Entries,Standardbucheinträge einschließen,
Include Exploded Items,Unterartikel einbeziehen,
Include POS Transactions,POS-Transaktionen einschließen,
Include UOM,Fügen Sie UOM hinzu,

Can't render this file because it is too large.

View File

@ -1153,7 +1153,7 @@ In Value,στην Αξία,
"In the case of multi-tier program, Customers will be auto assigned to the concerned tier as per their spent","Στην περίπτωση προγράμματος πολλαπλών βαθμίδων, οι Πελάτες θα αντιστοιχούν αυτόματα στη σχετική βαθμίδα σύμφωνα με το ποσό που δαπανώνται",
Inactive,Αδρανής,
Incentives,Κίνητρα,
Include Default Book Entries,Συμπεριλάβετε τις προεπιλεγμένες καταχωρίσεις βιβλίων,
Include Default FB Entries,Συμπεριλάβετε τις προεπιλεγμένες καταχωρίσεις βιβλίων,
Include Exploded Items,Συμπεριλάβετε εκραγμένα στοιχεία,
Include POS Transactions,Συμπεριλάβετε τις συναλλαγές POS,
Include UOM,Συμπεριλάβετε UOM,

Can't render this file because it is too large.

View File

@ -1153,7 +1153,7 @@ In Value,En valor,
"In the case of multi-tier program, Customers will be auto assigned to the concerned tier as per their spent","En el caso del programa de varios niveles, los Clientes se asignarán automáticamente al nivel correspondiente según su gasto",
Inactive,Inactivo,
Incentives,Incentivos,
Include Default Book Entries,Incluir entradas de libro predeterminadas,
Include Default FB Entries,Incluir entradas de libro predeterminadas,
Include Exploded Items,Incluir Elementos Estallados,
Include POS Transactions,Incluir transacciones POS,
Include UOM,Incluir UOM,

Can't render this file because it is too large.

View File

@ -1153,7 +1153,7 @@ In Value,väärtuse,
"In the case of multi-tier program, Customers will be auto assigned to the concerned tier as per their spent",Mitmekordsete programmide korral määratakse Kliendid automaatselt asjaomasele tasemele vastavalt nende kasutatud kuludele,
Inactive,Mitteaktiivne,
Incentives,Soodustused,
Include Default Book Entries,Lisage vaikeraamatu kanded,
Include Default FB Entries,Lisage vaikeraamatu kanded,
Include Exploded Items,Kaasa lõhutud esemed,
Include POS Transactions,Kaasa POS-tehingud,
Include UOM,Lisa UOM,

1 "Customer Provided Item" cannot be Purchase Item also &quot;Kliendiga varustatav toode&quot; ei saa olla ka ostuartikkel
1153 In the case of multi-tier program, Customers will be auto assigned to the concerned tier as per their spent Mitmekordsete programmide korral määratakse Kliendid automaatselt asjaomasele tasemele vastavalt nende kasutatud kuludele
1154 Inactive Mitteaktiivne
1155 Incentives Soodustused
1156 Include Default Book Entries Include Default FB Entries Lisage vaikeraamatu kanded
1157 Include Exploded Items Kaasa lõhutud esemed
1158 Include POS Transactions Kaasa POS-tehingud
1159 Include UOM Lisa UOM

View File

@ -1153,7 +1153,7 @@ In Value,با ارزش,
"In the case of multi-tier program, Customers will be auto assigned to the concerned tier as per their spent",در مورد برنامه چند لایه، مشتریان به صورت خودکار به سطر مربوطه اختصاص داده می شوند، همانطور که در هزینه های خود هستند,
Inactive,غیر فعال,
Incentives,انگیزه,
Include Default Book Entries,شامل ورودی های پیش فرض کتاب,
Include Default FB Entries,شامل ورودی های پیش فرض کتاب,
Include Exploded Items,شامل موارد انفجار,
Include POS Transactions,شامل معاملات POS,
Include UOM,شامل UOM,

Can't render this file because it is too large.

View File

@ -1153,7 +1153,7 @@ In Value,in Arvo,
"In the case of multi-tier program, Customers will be auto assigned to the concerned tier as per their spent",Monitasoisen ohjelman tapauksessa asiakkaat määräytyvät automaattisesti kyseiselle tasolle niiden kulutuksen mukaan,
Inactive,Epäaktiivinen,
Incentives,kannustimet/bonukset,
Include Default Book Entries,Sisällytä oletustiedot,
Include Default FB Entries,Sisällytä oletustiedot,
Include Exploded Items,Sisällytä räjähtämättömiä kohteita,
Include POS Transactions,Sisällytä POS-tapahtumia,
Include UOM,Sisällytä UOM,

Can't render this file because it is too large.

View File

@ -1153,7 +1153,7 @@ In Value,En valeur,
"In the case of multi-tier program, Customers will be auto assigned to the concerned tier as per their spent","Dans le cas d'un programme à plusieurs échelons, les clients seront automatiquement affectés au niveau approprié en fonction de leurs dépenses",
Inactive,Inactif,
Incentives,Incitations,
Include Default Book Entries,Inclure les entrées de livre par défaut,
Include Default FB Entries,Inclure les entrées de livre par défaut,
Include Exploded Items,Inclure les articles éclatés,
Include POS Transactions,Inclure les transactions du point de vente,
Include UOM,Inclure UdM,

Can't render this file because it is too large.

View File

@ -1153,7 +1153,7 @@ In Value,ભાવ,
"In the case of multi-tier program, Customers will be auto assigned to the concerned tier as per their spent","મલ્ટિ-ટાયર પ્રોગ્રામના કિસ્સામાં, ગ્રાહક તેમના ખર્ચ મુજબ સંબંધિત ટાયરમાં ઓટો હશે",
Inactive,નિષ્ક્રિય,
Incentives,ઇનસેન્ટીવ્સ,
Include Default Book Entries,ડિફaultલ્ટ બુક એન્ટ્રીઓ શામેલ કરો,
Include Default FB Entries,ડિફaultલ્ટ બુક એન્ટ્રીઓ શામેલ કરો,
Include Exploded Items,વિસ્ફોટ થયેલ આઇટમ્સ શામેલ કરો,
Include POS Transactions,POS વ્યવહારો શામેલ કરો,
Include UOM,યુએમએમ શામેલ કરો,

Can't render this file because it is too large.

View File

@ -1153,7 +1153,7 @@ In Value,ערך,
"In the case of multi-tier program, Customers will be auto assigned to the concerned tier as per their spent","במקרה של תוכנית רב-שכבתית, הלקוחות יוקצו אוטומטית לשכבה הנוגעת בדבר שהוצאו",
Inactive,לֹא פָּעִיל,
Incentives,תמריצים,
Include Default Book Entries,כלול רשומות ברירת מחדל לספרים,
Include Default FB Entries,כלול רשומות ברירת מחדל לספרים,
Include Exploded Items,כלול פריטים מפוצצים,
Include POS Transactions,כלול עסקאות קופה,
Include UOM,כלול UOM,

Can't render this file because it is too large.

View File

@ -1153,7 +1153,7 @@ In Value,मूल्य में,
"In the case of multi-tier program, Customers will be auto assigned to the concerned tier as per their spent","मल्टी-स्तरीय कार्यक्रम के मामले में, ग्राहक अपने खर्च के अनुसार संबंधित स्तर को स्वचालित रूप से सौंपा जाएगा",
Inactive,निष्क्रिय,
Incentives,प्रोत्साहन,
Include Default Book Entries,डिफ़ॉल्ट बुक प्रविष्टियाँ शामिल करें,
Include Default FB Entries,डिफ़ॉल्ट बुक प्रविष्टियाँ शामिल करें,
Include Exploded Items,विस्फोट किए गए आइटम शामिल करें,
Include POS Transactions,पीओएस लेनदेन शामिल करें,
Include UOM,यूओएम शामिल करें,

Can't render this file because it is too large.

View File

@ -1153,7 +1153,7 @@ In Value,u vrijednost,
"In the case of multi-tier program, Customers will be auto assigned to the concerned tier as per their spent","U slučaju višerazinskog programa, Kupci će biti automatski dodijeljeni odgovarajućem stupcu po njihovu potrošenom",
Inactive,neaktivan,
Incentives,poticaji,
Include Default Book Entries,Uključite zadane unose u knjige,
Include Default FB Entries,Uključite zadane unose u knjige,
Include Exploded Items,Uključi eksplodirane predmete,
Include POS Transactions,Uključi POS transakcije,
Include UOM,Uključi UOM,

Can't render this file because it is too large.

View File

@ -1153,7 +1153,7 @@ In Value,Az Értékben,
"In the case of multi-tier program, Customers will be auto assigned to the concerned tier as per their spent","Többszintű program esetében az ügyfeleket automatikusan az adott kategóriába sorolják, az általuk elköltöttek szerint",
Inactive,Inaktív,
Incentives,Ösztönzők,
Include Default Book Entries,Tartalmazza az alapértelmezett könyvbejegyzéseket,
Include Default FB Entries,Tartalmazza az alapértelmezett könyvbejegyzéseket,
Include Exploded Items,Tartalmazza a robbantott elemeket,
Include POS Transactions,Tartalmazza a POS kassza tranzakciókat,
Include UOM,Ide tartozik az ANYJ,

Can't render this file because it is too large.

View File

@ -1153,7 +1153,7 @@ In Value,Nilai,
"In the case of multi-tier program, Customers will be auto assigned to the concerned tier as per their spent","Dalam kasus program multi-tier, Pelanggan akan ditugaskan secara otomatis ke tingkat yang bersangkutan sesuai yang mereka habiskan",
Inactive,Tidak aktif,
Incentives,Insentif,
Include Default Book Entries,Sertakan Entri Buku Default,
Include Default FB Entries,Sertakan Entri Buku Default,
Include Exploded Items,Sertakan barang yang meledak,
Include POS Transactions,Sertakan Transaksi POS,
Include UOM,Termasuk UOM,

Can't render this file because it is too large.

View File

@ -1153,7 +1153,7 @@ In Value,Virði,
"In the case of multi-tier program, Customers will be auto assigned to the concerned tier as per their spent","Þegar um er að ræða fjölþættaráætlun, verða viðskiptavinir sjálfkrafa tengdir viðkomandi flokka eftir því sem þeir eru í",
Inactive,Óvirkt,
Incentives,Incentives,
Include Default Book Entries,Hafa sjálfgefnar bókarfærslur með,
Include Default FB Entries,Hafa sjálfgefnar bókarfærslur með,
Include Exploded Items,Inniheldur sprauta hluti,
Include POS Transactions,Innifalið POS-viðskipti,
Include UOM,Innifalið UOM,

Can't render this file because it is too large.

View File

@ -1153,7 +1153,7 @@ In Value,In valore,
"In the case of multi-tier program, Customers will be auto assigned to the concerned tier as per their spent","Nel caso di un programma multilivello, i clienti verranno assegnati automaticamente al livello interessato come da loro speso",
Inactive,Inattivo,
Incentives,Incentivi,
Include Default Book Entries,Includi voci di libro predefinite,
Include Default FB Entries,Includi voci di libro predefinite,
Include Exploded Items,Includi elementi esplosi,
Include POS Transactions,Includi transazioni POS,
Include UOM,Includi UOM,

Can't render this file because it is too large.

View File

@ -1153,7 +1153,7 @@ In Value,値内,
"In the case of multi-tier program, Customers will be auto assigned to the concerned tier as per their spent",マルチティアプログラムの場合、顧客は、消費されるごとに自動的に関係する層に割り当てられます,
Inactive,非アクティブ,
Incentives,インセンティブ,
Include Default Book Entries,デフォルトのブックエントリを含める,
Include Default FB Entries,デフォルトのブックエントリを含める,
Include Exploded Items,分解された項目を含める,
Include POS Transactions,POSトランザクションを含める,
Include UOM,UOMを含める,

Can't render this file because it is too large.

View File

@ -1153,7 +1153,7 @@ In Value,នៅក្នុងតម្លៃ,
"In the case of multi-tier program, Customers will be auto assigned to the concerned tier as per their spent",ក្នុងករណីមានកម្មវិធីពហុលំដាប់អតិថិជននឹងត្រូវបានចាត់តាំងដោយខ្លួនឯងទៅថ្នាក់ដែលពាក់ព័ន្ធដោយចំណាយរបស់ពួកគេ,
Inactive,អសកម្ម,
Incentives,ការលើកទឹកចិត្ត,
Include Default Book Entries,រួមបញ្ចូលធាតុសៀវភៅលំនាំដើម។,
Include Default FB Entries,រួមបញ្ចូលធាតុសៀវភៅលំនាំដើម។,
Include Exploded Items,រួមបញ្ចូលធាតុផ្ទុះ,
Include POS Transactions,បញ្ចូលប្រតិបត្តិការ POS,
Include UOM,រួមបញ្ចូល UOM,

Can't render this file because it is too large.

View File

@ -1153,7 +1153,7 @@ In Value,ಮೌಲ್ಯ,
"In the case of multi-tier program, Customers will be auto assigned to the concerned tier as per their spent","ಮಲ್ಟಿ-ಟೈರ್ ಪ್ರೋಗ್ರಾಂನ ಸಂದರ್ಭದಲ್ಲಿ, ಗ್ರಾಹಕರು ತಮ್ಮ ಖರ್ಚುಗೆ ಅನುಗುಣವಾಗಿ ಆಯಾ ಶ್ರೇಣಿಗೆ ಸ್ವಯಂ ನಿಯೋಜಿಸಲಾಗುವುದು",
Inactive,ನಿಷ್ಕ್ರಿಯವಾಗಿದೆ,
Incentives,ಪ್ರೋತ್ಸಾಹ,
Include Default Book Entries,ಡೀಫಾಲ್ಟ್ ಪುಸ್ತಕ ನಮೂದುಗಳನ್ನು ಸೇರಿಸಿ,
Include Default FB Entries,ಡೀಫಾಲ್ಟ್ ಪುಸ್ತಕ ನಮೂದುಗಳನ್ನು ಸೇರಿಸಿ,
Include Exploded Items,ಸ್ಫೋಟಗೊಂಡ ವಸ್ತುಗಳನ್ನು ಸೇರಿಸಿ,
Include POS Transactions,ಪಿಒಎಸ್ ಟ್ರಾನ್ಸಾಕ್ಷನ್ಸ್ ಸೇರಿಸಿ,
Include UOM,UOM ಸೇರಿಸಿ,

Can't render this file because it is too large.

View File

@ -1153,7 +1153,7 @@ In Value,값에서,
"In the case of multi-tier program, Customers will be auto assigned to the concerned tier as per their spent",다중 계층 프로그램의 경우 고객은 지출 한대로 해당 계층에 자동으로 할당됩니다.,
Inactive,비활성,
Incentives,장려책,
Include Default Book Entries,기본 도서 항목 포함,
Include Default FB Entries,기본 도서 항목 포함,
Include Exploded Items,분해 된 항목 포함,
Include POS Transactions,POS 트랜잭션 포함,
Include UOM,UOM 포함,

Can't render this file because it is too large.

View File

@ -1153,7 +1153,7 @@ In Value,di Nirx,
"In the case of multi-tier program, Customers will be auto assigned to the concerned tier as per their spent","Di rewşê de bernameya pir-tier, Ewrûpa dê ji hêla xercê xwe ve girêdayî xerîb be",
Inactive,Bêkar,
Incentives,aborîve,
Include Default Book Entries,Navnîşanên Pirtûka Pêvek Bawer bikin,
Include Default FB Entries,Navnîşanên Pirtûka Pêvek Bawer bikin,
Include Exploded Items,Included Dead Items,
Include POS Transactions,Têkiliyên POSê de,
Include UOM,UOM,

Can't render this file because it is too large.

View File

@ -1153,7 +1153,7 @@ In Value,ໃນມູນຄ່າ,
"In the case of multi-tier program, Customers will be auto assigned to the concerned tier as per their spent","ໃນກໍລະນີຂອງໂຄງການຫຼາຍຂັ້ນ, ລູກຄ້າຈະໄດ້ຮັບການມອບຫມາຍໂດຍອັດຕະໂນມັດໃຫ້ກັບຂັ້ນຕອນທີ່ກ່ຽວຂ້ອງຕາມການໃຊ້ຈ່າຍຂອງເຂົາເຈົ້າ",
Inactive,Inactive,
Incentives,ສິ່ງຈູງໃຈ,
Include Default Book Entries,ລວມທັງການອອກສຽງປື້ມແບບເລີ່ມຕົ້ນ,
Include Default FB Entries,ລວມທັງການອອກສຽງປື້ມແບບເລີ່ມຕົ້ນ,
Include Exploded Items,ລວມເອົາສິ່ງທີ່ເກີດຂື້ນ,
Include POS Transactions,ລວມທຸລະກໍາ POS,
Include UOM,ລວມ UOM,

Can't render this file because it is too large.

View File

@ -1153,7 +1153,7 @@ In Value,vertės,
"In the case of multi-tier program, Customers will be auto assigned to the concerned tier as per their spent","Kalbant apie daugiapakopę programą, klientai bus automatiškai priskirti atitinkamam lygmeniui, atsižvelgiant į jų išleidimą",
Inactive,Neaktyvus,
Incentives,Paskatos,
Include Default Book Entries,Įtraukite numatytuosius knygų įrašus,
Include Default FB Entries,Įtraukite numatytuosius knygų įrašus,
Include Exploded Items,Įtraukti sprogus elementus,
Include POS Transactions,Įtraukti POS operacijas,
Include UOM,Įtraukti UOM,

Can't render this file because it is too large.

View File

@ -1153,7 +1153,7 @@ In Value,Vērtībā,
"In the case of multi-tier program, Customers will be auto assigned to the concerned tier as per their spent","Daudzpakāpju programmas gadījumā Klienti tiks automātiski piešķirti attiecīgajam līmenim, salīdzinot ar viņu iztērēto",
Inactive,Neaktīvs,
Incentives,Stimuli,
Include Default Book Entries,Iekļaujiet noklusējuma grāmatas ierakstus,
Include Default FB Entries,Iekļaujiet noklusējuma grāmatas ierakstus,
Include Exploded Items,Iekļaut izpūstas preces,
Include POS Transactions,Iekļaut POS darījumus,
Include UOM,Iekļaut UOM,

Can't render this file because it is too large.

View File

@ -1153,7 +1153,7 @@ In Value,Во вредност,
"In the case of multi-tier program, Customers will be auto assigned to the concerned tier as per their spent","Во случај на повеќеслојна програма, корисниците ќе бидат автоматски доделени на засегнатите нивоа, како на нивните потрошени",
Inactive,Неактивен,
Incentives,Стимулации,
Include Default Book Entries,Вклучете стандардни записи за книги,
Include Default FB Entries,Вклучете стандардни записи за книги,
Include Exploded Items,Вклучи експлодирани елементи,
Include POS Transactions,Вклучете POS-трансакции,
Include UOM,Вклучете UOM,

Can't render this file because it is too large.

View File

@ -1153,7 +1153,7 @@ In Value,മൂല്യത്തിൽ,
"In the case of multi-tier program, Customers will be auto assigned to the concerned tier as per their spent","മൾട്ടി-ടയർ പരിപാടിയുടെ കാര്യത്തിൽ, കസ്റ്റമർമാർ ചെലവഴിച്ച തുക പ്രകാരം ബന്ധപ്പെട്ട ടീമിൽ ഓട്ടോ നിർണ്ണയിക്കും",
Inactive,നിഷ്ക്രിയം,
Incentives,ഇൻസെന്റീവ്സ്,
Include Default Book Entries,സ്ഥിരസ്ഥിതി പുസ്തക എൻ‌ട്രികൾ‌ ഉൾ‌പ്പെടുത്തുക,
Include Default FB Entries,സ്ഥിരസ്ഥിതി പുസ്തക എൻ‌ട്രികൾ‌ ഉൾ‌പ്പെടുത്തുക,
Include Exploded Items,എക്സ്പ്ലോഡഡ് ഇനങ്ങൾ ഉൾപ്പെടുത്തുക,
Include POS Transactions,POS ഇടപാടുകൾ ഉൾപ്പെടുത്തുക,
Include UOM,UOM ഉൾപ്പെടുത്തുക,

Can't render this file because it is too large.

View File

@ -1153,7 +1153,7 @@ In Value,मूल्य,
"In the case of multi-tier program, Customers will be auto assigned to the concerned tier as per their spent",बहु-स्तरीय कार्यक्रमाच्या बाबतीत ग्राहक त्यांच्या खर्चानुसार संबंधित टायरला स्वयंचलितरित्या नियुक्त केले जातील,
Inactive,निष्क्रिय,
Incentives,प्रोत्साहन,
Include Default Book Entries,डीफॉल्ट पुस्तक नोंदी समाविष्ट करा,
Include Default FB Entries,डीफॉल्ट पुस्तक नोंदी समाविष्ट करा,
Include Exploded Items,विस्फोट केलेल्या वस्तू समाविष्ट करा,
Include POS Transactions,पीओएस व्यवहार समाविष्ट करा,
Include UOM,यूओएम समाविष्ट करा,

Can't render this file because it is too large.

View File

@ -1153,7 +1153,7 @@ In Value,Dalam Nilai,
"In the case of multi-tier program, Customers will be auto assigned to the concerned tier as per their spent","Dalam hal program multi-tier, Pelanggan akan ditugaskan secara automatik ke peringkat yang bersangkutan seperti yang dibelanjakannya",
Inactive,Tidak aktif,
Incentives,Insentif,
Include Default Book Entries,Sertakan Penyertaan Buku Lalai,
Include Default FB Entries,Sertakan Penyertaan Buku Lalai,
Include Exploded Items,Termasuk Item Meletup,
Include POS Transactions,Termasuk Transaksi POS,
Include UOM,Termasuk UOM,

Can't render this file because it is too large.

View File

@ -1153,7 +1153,7 @@ In Value,Value တစ်ခုအတွက်,
"In the case of multi-tier program, Customers will be auto assigned to the concerned tier as per their spent","Multi-tier အစီအစဉ်၏အမှု၌, Customer များအလိုအလျောက်သူတို့ရဲ့သုံးစွဲနှုန်းအတိုင်းစိုးရိမ်ပူပန်ဆင့်မှတာဝန်ပေးအပ်ပါလိမ့်မည်",
Inactive,မလှုပ်ရှားတတ်သော,
Incentives,မက်လုံးတွေပေးပြီး,
Include Default Book Entries,ပုံမှန်စာအုပ် Entries Include,
Include Default FB Entries,ပုံမှန်စာအုပ် Entries Include,
Include Exploded Items,ပေါက်ကွဲပစ္စည်းများ Include,
Include POS Transactions,POS အရောင်းအဝယ် Include,
Include UOM,UOM Include,

Can't render this file because it is too large.

View File

@ -1153,7 +1153,7 @@ In Value,in Value,
"In the case of multi-tier program, Customers will be auto assigned to the concerned tier as per their spent",In het geval van een meerlagig programma worden klanten automatisch toegewezen aan de betreffende laag op basis van hun bestede tijd,
Inactive,Inactief,
Incentives,Incentives,
Include Default Book Entries,Standaard boekvermeldingen opnemen,
Include Default FB Entries,Standaard boekvermeldingen opnemen,
Include Exploded Items,Exploded Items opnemen,
Include POS Transactions,POS-transacties opnemen,
Include UOM,Inclusief UOM,

Can't render this file because it is too large.

View File

@ -1153,7 +1153,7 @@ In Value,I verdi,
"In the case of multi-tier program, Customers will be auto assigned to the concerned tier as per their spent","Når det gjelder flerlagsprogram, vil kundene automatisk bli tilordnet den aktuelle delen som brukt",
Inactive,inaktiv,
Incentives,Motivasjon,
Include Default Book Entries,Inkluder standardbokoppføringer,
Include Default FB Entries,Inkluder standardbokoppføringer,
Include Exploded Items,Inkluder eksploderte elementer,
Include POS Transactions,Inkluder POS-transaksjoner,
Include UOM,Inkluder UOM,

1 "Customer Provided Item" cannot be Purchase Item also &quot;Kundeleveret vare&quot; kan ikke være kjøpsvarer også
1153 In the case of multi-tier program, Customers will be auto assigned to the concerned tier as per their spent Når det gjelder flerlagsprogram, vil kundene automatisk bli tilordnet den aktuelle delen som brukt
1154 Inactive inaktiv
1155 Incentives Motivasjon
1156 Include Default Book Entries Include Default FB Entries Inkluder standardbokoppføringer
1157 Include Exploded Items Inkluder eksploderte elementer
1158 Include POS Transactions Inkluder POS-transaksjoner
1159 Include UOM Inkluder UOM

View File

@ -1151,7 +1151,7 @@ In Stock: ,W magazynie:,
In Value,w polu Wartość,
"In the case of multi-tier program, Customers will be auto assigned to the concerned tier as per their spent","W przypadku programu wielowarstwowego Klienci zostaną automatycznie przypisani do danego poziomu, zgodnie z wydatkami",
Inactive,Nieaktywny,
Include Default Book Entries,Dołącz domyślne wpisy książki,
Include Default FB Entries,Dołącz domyślne wpisy książki,
Include Exploded Items,Dołącz rozstrzelone przedmioty,
Include POS Transactions,Uwzględnij transakcje POS,
Include UOM,Dołącz UOM,

Can't render this file because it is too large.

View File

@ -1153,7 +1153,7 @@ In Value,په ارزښت,
"In the case of multi-tier program, Customers will be auto assigned to the concerned tier as per their spent",د څو اړخیز پروګرام په صورت کې، پیرودونکي به د خپل مصرف په اساس اړوند ټیټ ته ګمارل کیږي,
Inactive,غیر فعال,
Incentives,هڅوونکي,
Include Default Book Entries,د ډیفالټ کتاب ننوتل شامل کړئ,
Include Default FB Entries,د ډیفالټ کتاب ننوتل شامل کړئ,
Include Exploded Items,چاودیدونکي توکي شامل کړئ,
Include POS Transactions,د POS تعاملات شامل کړئ,
Include UOM,UOM شامل کړئ,

Can't render this file because it is too large.

View File

@ -1153,7 +1153,7 @@ In Value,Valor Entrada,
"In the case of multi-tier program, Customers will be auto assigned to the concerned tier as per their spent","No caso do programa multicamadas, os Clientes serão atribuídos automaticamente ao nível em questão de acordo com o gasto",
Inactive,Inativo,
Incentives,Incentivos,
Include Default Book Entries,Incluir Entradas de Livro Padrão,
Include Default FB Entries,Incluir Entradas de Livro Padrão,
Include Exploded Items,Incluir Itens Explodidos,
Include POS Transactions,Incluir Transações PDV,
Include UOM,Incluir UDM,

Can't render this file because it is too large.

View File

@ -1153,7 +1153,7 @@ In Value,No Valor,
"In the case of multi-tier program, Customers will be auto assigned to the concerned tier as per their spent","No caso do programa multicamadas, os Clientes serão atribuídos automaticamente ao nível em questão de acordo com o gasto",
Inactive,Inativo,
Incentives,Incentivos,
Include Default Book Entries,Incluir entradas de livro padrão,
Include Default FB Entries,Incluir entradas de livro padrão,
Include Exploded Items,Incluir itens explodidos,
Include POS Transactions,Incluir transações POS,
Include UOM,Incluir UOM,

Can't render this file because it is too large.

View File

@ -1153,7 +1153,7 @@ In Value,În valoare,
"In the case of multi-tier program, Customers will be auto assigned to the concerned tier as per their spent","În cazul unui program cu mai multe niveluri, Clienții vor fi automat alocați nivelului respectiv în funcție de cheltuielile efectuate",
Inactive,Inactiv,
Incentives,stimulente,
Include Default Book Entries,Includeți intrări implicite în cărți,
Include Default FB Entries,Includeți intrări implicite în cărți,
Include Exploded Items,Includeți articole explodate,
Include POS Transactions,Includeți tranzacțiile POS,
Include UOM,Includeți UOM,

Can't render this file because it is too large.

View File

@ -1151,7 +1151,7 @@ In Value,В цене,
"In the case of multi-tier program, Customers will be auto assigned to the concerned tier as per their spent",В случае многоуровневой программы Клиенты будут автоматически назначены соответствующему уровню в соответствии с затраченными,
Inactive,Неактивный,
Incentives,Стимулирование,
Include Default Book Entries,Включить записи в книгу по умолчанию,
Include Default FB Entries,Включить записи в книгу по умолчанию,
Include Exploded Items,Включить раздробленные элементы,
Include POS Transactions,Включить POS-транзакции,
Include UOM,Включить UOM,

Can't render this file because it is too large.

View File

@ -1153,7 +1153,7 @@ In Value,Agaciro,
"In the case of multi-tier program, Customers will be auto assigned to the concerned tier as per their spent","Kubijyanye na gahunda yo mu byiciro byinshi, Abakiriya bazahabwa imodoka bashinzwe urwego bireba nkuko bakoresheje",
Inactive,Kudakora,
Incentives,Inkunga,
Include Default Book Entries,Shyiramo Ibisanzwe Byanditswe,
Include Default FB Entries,Shyiramo Ibisanzwe Byanditswe,
Include Exploded Items,Shyiramo Ibintu Biturika,
Include POS Transactions,Shyiramo ibikorwa bya POS,
Include UOM,Shyiramo UOM,

Can't render this file because it is too large.

View File

@ -1153,7 +1153,7 @@ In Value,අගය දී,
"In the case of multi-tier program, Customers will be auto assigned to the concerned tier as per their spent","බහු ස්ථරයේ වැඩසටහනක දී, පාරිභෝගිකයින් විසින් වැය කරනු ලබන පරිදි පාරිභෝගිකයින්ට අදාල ස්ථානයට ස්වයංක්රීයව පවරනු ලැබේ",
Inactive,අක්රියයි,
Incentives,සහන,
Include Default Book Entries,පෙරනිමි පොත් ඇතුළත් කිරීම් ඇතුළත් කරන්න,
Include Default FB Entries,පෙරනිමි පොත් ඇතුළත් කිරීම් ඇතුළත් කරන්න,
Include Exploded Items,පුපුරණ ද්රව්ය අඩංගු කරන්න,
Include POS Transactions,POS ගනුදෙනු,
Include UOM,UOM ඇතුළත් කරන්න,

Can't render this file because it is too large.

View File

@ -1153,7 +1153,7 @@ In Value,v Hodnota,
"In the case of multi-tier program, Customers will be auto assigned to the concerned tier as per their spent",V prípade viacvrstvového programu budú zákazníci automaticky priradení príslušnému vrstvu podľa ich vynaložených prostriedkov,
Inactive,neaktívne,
Incentives,Pobídky,
Include Default Book Entries,Zahrnúť predvolené položky knihy,
Include Default FB Entries,Zahrnúť predvolené položky knihy,
Include Exploded Items,Zahrňte explodované položky,
Include POS Transactions,Zahrňte POS transakcie,
Include UOM,Zahrňte UOM,

Can't render this file because it is too large.

View File

@ -1153,7 +1153,7 @@ In Value,V vrednosti,
"In the case of multi-tier program, Customers will be auto assigned to the concerned tier as per their spent",V primeru večstopenjskega programa bodo stranke samodejno dodeljene zadevni stopnji glede na porabljene,
Inactive,Neaktivno,
Incentives,Spodbude,
Include Default Book Entries,Vključi privzete vnose v knjige,
Include Default FB Entries,Vključi privzete vnose v knjige,
Include Exploded Items,Vključi eksplodirane elemente,
Include POS Transactions,Vključite POS transakcije,
Include UOM,Vključi UOM,

Can't render this file because it is too large.

View File

@ -1153,7 +1153,7 @@ In Value,Në Vlera,
"In the case of multi-tier program, Customers will be auto assigned to the concerned tier as per their spent","Në rastin e programit multi-shtresor, Konsumatorët do të caktohen automatikisht në nivelin përkatës sipas shpenzimeve të tyre",
Inactive,joaktiv,
Incentives,Nxitjet,
Include Default Book Entries,Përfshini hyrje të librave të paracaktuar,
Include Default FB Entries,Përfshini hyrje të librave të paracaktuar,
Include Exploded Items,Përfshirja e artikujve të eksploduar,
Include POS Transactions,Përfshi transaksione POS,
Include UOM,Përfshi UOM,

Can't render this file because it is too large.

View File

@ -1153,7 +1153,7 @@ In Value,У вредности,
"In the case of multi-tier program, Customers will be auto assigned to the concerned tier as per their spent","У случају мулти-тиер програма, Корисници ће аутоматски бити додијељени за одређени ниво према њиховом потрошеном",
Inactive,Неактиван,
Incentives,Подстицаји,
Include Default Book Entries,Укључивање заданих уноса у књиге,
Include Default FB Entries,Укључивање заданих уноса у књиге,
Include Exploded Items,Укључите експлодиране ставке,
Include POS Transactions,Укључите ПОС трансакције,
Include UOM,Укључите УОМ,

Can't render this file because it is too large.

View File

@ -1153,7 +1153,7 @@ In Value,Värde,
"In the case of multi-tier program, Customers will be auto assigned to the concerned tier as per their spent",När det gäller program med flera nivåer kommer kunderna automatiskt att tilldelas den aktuella tiern enligt deras tillbringade,
Inactive,Inaktiv,
Incentives,Sporen,
Include Default Book Entries,Inkludera standardbokposter,
Include Default FB Entries,Inkludera standardbokposter,
Include Exploded Items,Inkludera explosiva artiklar,
Include POS Transactions,Inkludera POS-transaktioner,
Include UOM,Inkludera UOM,

Can't render this file because it is too large.

Some files were not shown because too many files have changed in this diff Show More