mirror of
https://github.com/frappe/erpnext.git
synced 2026-05-23 23:19:20 +00:00
Merge branch 'develop' into rfq-email
This commit is contained in:
@@ -195,88 +195,91 @@ def create_sales_invoice_record(qty=1):
|
|||||||
|
|
||||||
def create_records():
|
def create_records():
|
||||||
# create a new loyalty Account
|
# create a new loyalty Account
|
||||||
if frappe.db.exists("Account", "Loyalty - _TC"):
|
if not frappe.db.exists("Account", "Loyalty - _TC"):
|
||||||
return
|
frappe.get_doc({
|
||||||
|
"doctype": "Account",
|
||||||
frappe.get_doc({
|
"account_name": "Loyalty",
|
||||||
"doctype": "Account",
|
"parent_account": "Direct Expenses - _TC",
|
||||||
"account_name": "Loyalty",
|
"company": "_Test Company",
|
||||||
"parent_account": "Direct Expenses - _TC",
|
"is_group": 0,
|
||||||
"company": "_Test Company",
|
"account_type": "Expense Account",
|
||||||
"is_group": 0,
|
}).insert()
|
||||||
"account_type": "Expense Account",
|
|
||||||
}).insert()
|
|
||||||
|
|
||||||
# create a new loyalty program Single tier
|
# create a new loyalty program Single tier
|
||||||
frappe.get_doc({
|
if not frappe.db.exists("Loyalty Program","Test Single Loyalty"):
|
||||||
"doctype": "Loyalty Program",
|
frappe.get_doc({
|
||||||
"loyalty_program_name": "Test Single Loyalty",
|
"doctype": "Loyalty Program",
|
||||||
"auto_opt_in": 1,
|
"loyalty_program_name": "Test Single Loyalty",
|
||||||
"from_date": today(),
|
"auto_opt_in": 1,
|
||||||
"loyalty_program_type": "Single Tier Program",
|
"from_date": today(),
|
||||||
"conversion_factor": 1,
|
"loyalty_program_type": "Single Tier Program",
|
||||||
"expiry_duration": 10,
|
"conversion_factor": 1,
|
||||||
"company": "_Test Company",
|
"expiry_duration": 10,
|
||||||
"cost_center": "Main - _TC",
|
"company": "_Test Company",
|
||||||
"expense_account": "Loyalty - _TC",
|
"cost_center": "Main - _TC",
|
||||||
"collection_rules": [{
|
"expense_account": "Loyalty - _TC",
|
||||||
'tier_name': 'Silver',
|
"collection_rules": [{
|
||||||
'collection_factor': 1000,
|
|
||||||
'min_spent': 1000
|
|
||||||
}]
|
|
||||||
}).insert()
|
|
||||||
|
|
||||||
# create a new customer
|
|
||||||
frappe.get_doc({
|
|
||||||
"customer_group": "_Test Customer Group",
|
|
||||||
"customer_name": "Test Loyalty Customer",
|
|
||||||
"customer_type": "Individual",
|
|
||||||
"doctype": "Customer",
|
|
||||||
"territory": "_Test Territory"
|
|
||||||
}).insert()
|
|
||||||
|
|
||||||
# create a new loyalty program Multiple tier
|
|
||||||
frappe.get_doc({
|
|
||||||
"doctype": "Loyalty Program",
|
|
||||||
"loyalty_program_name": "Test Multiple Loyalty",
|
|
||||||
"auto_opt_in": 1,
|
|
||||||
"from_date": today(),
|
|
||||||
"loyalty_program_type": "Multiple Tier Program",
|
|
||||||
"conversion_factor": 1,
|
|
||||||
"expiry_duration": 10,
|
|
||||||
"company": "_Test Company",
|
|
||||||
"cost_center": "Main - _TC",
|
|
||||||
"expense_account": "Loyalty - _TC",
|
|
||||||
"collection_rules": [
|
|
||||||
{
|
|
||||||
'tier_name': 'Silver',
|
'tier_name': 'Silver',
|
||||||
'collection_factor': 1000,
|
'collection_factor': 1000,
|
||||||
'min_spent': 10000
|
'min_spent': 1000
|
||||||
},
|
}]
|
||||||
{
|
}).insert()
|
||||||
'tier_name': 'Gold',
|
|
||||||
'collection_factor': 1000,
|
# create a new customer
|
||||||
'min_spent': 19000
|
if not frappe.db.exists("Customer","Test Loyalty Customer"):
|
||||||
}
|
frappe.get_doc({
|
||||||
]
|
"customer_group": "_Test Customer Group",
|
||||||
}).insert()
|
"customer_name": "Test Loyalty Customer",
|
||||||
|
"customer_type": "Individual",
|
||||||
|
"doctype": "Customer",
|
||||||
|
"territory": "_Test Territory"
|
||||||
|
}).insert()
|
||||||
|
|
||||||
|
# create a new loyalty program Multiple tier
|
||||||
|
if not frappe.db.exists("Loyalty Program","Test Multiple Loyalty"):
|
||||||
|
frappe.get_doc({
|
||||||
|
"doctype": "Loyalty Program",
|
||||||
|
"loyalty_program_name": "Test Multiple Loyalty",
|
||||||
|
"auto_opt_in": 1,
|
||||||
|
"from_date": today(),
|
||||||
|
"loyalty_program_type": "Multiple Tier Program",
|
||||||
|
"conversion_factor": 1,
|
||||||
|
"expiry_duration": 10,
|
||||||
|
"company": "_Test Company",
|
||||||
|
"cost_center": "Main - _TC",
|
||||||
|
"expense_account": "Loyalty - _TC",
|
||||||
|
"collection_rules": [
|
||||||
|
{
|
||||||
|
'tier_name': 'Silver',
|
||||||
|
'collection_factor': 1000,
|
||||||
|
'min_spent': 10000
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'tier_name': 'Gold',
|
||||||
|
'collection_factor': 1000,
|
||||||
|
'min_spent': 19000
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}).insert()
|
||||||
|
|
||||||
# create an item
|
# create an item
|
||||||
item = frappe.get_doc({
|
if not frappe.db.exists("Item", "Loyal Item"):
|
||||||
"doctype": "Item",
|
frappe.get_doc({
|
||||||
"item_code": "Loyal Item",
|
"doctype": "Item",
|
||||||
"item_name": "Loyal Item",
|
"item_code": "Loyal Item",
|
||||||
"item_group": "All Item Groups",
|
"item_name": "Loyal Item",
|
||||||
"company": "_Test Company",
|
"item_group": "All Item Groups",
|
||||||
"is_stock_item": 1,
|
"company": "_Test Company",
|
||||||
"opening_stock": 100,
|
"is_stock_item": 1,
|
||||||
"valuation_rate": 10000,
|
"opening_stock": 100,
|
||||||
}).insert()
|
"valuation_rate": 10000,
|
||||||
|
}).insert()
|
||||||
|
|
||||||
# create item price
|
# create item price
|
||||||
frappe.get_doc({
|
if not frappe.db.exists("Item Price", {"price_list": "Standard Selling", "item_code": "Loyal Item"}):
|
||||||
"doctype": "Item Price",
|
frappe.get_doc({
|
||||||
"price_list": "Standard Selling",
|
"doctype": "Item Price",
|
||||||
"item_code": item.item_code,
|
"price_list": "Standard Selling",
|
||||||
"price_list_rate": 10000
|
"item_code": "Loyal Item",
|
||||||
}).insert()
|
"price_list_rate": 10000
|
||||||
|
}).insert()
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ class TestPOSClosingEntry(unittest.TestCase):
|
|||||||
frappe.set_user("Administrator")
|
frappe.set_user("Administrator")
|
||||||
frappe.db.sql("delete from `tabPOS Profile`")
|
frappe.db.sql("delete from `tabPOS Profile`")
|
||||||
|
|
||||||
def init_user_and_profile():
|
def init_user_and_profile(**args):
|
||||||
user = 'test@example.com'
|
user = 'test@example.com'
|
||||||
test_user = frappe.get_doc('User', user)
|
test_user = frappe.get_doc('User', user)
|
||||||
|
|
||||||
@@ -53,7 +53,7 @@ def init_user_and_profile():
|
|||||||
test_user.add_roles(*roles)
|
test_user.add_roles(*roles)
|
||||||
frappe.set_user(user)
|
frappe.set_user(user)
|
||||||
|
|
||||||
pos_profile = make_pos_profile()
|
pos_profile = make_pos_profile(**args)
|
||||||
pos_profile.append('applicable_for_users', {
|
pos_profile.append('applicable_for_users', {
|
||||||
'default': 1,
|
'default': 1,
|
||||||
'user': user
|
'user': user
|
||||||
|
|||||||
@@ -139,7 +139,8 @@ class POSInvoice(SalesInvoice):
|
|||||||
frappe.throw(_("At least one mode of payment is required for POS invoice."))
|
frappe.throw(_("At least one mode of payment is required for POS invoice."))
|
||||||
|
|
||||||
def validate_change_account(self):
|
def validate_change_account(self):
|
||||||
if frappe.db.get_value("Account", self.account_for_change_amount, "company") != self.company:
|
if self.change_amount and self.account_for_change_amount and \
|
||||||
|
frappe.db.get_value("Account", self.account_for_change_amount, "company") != self.company:
|
||||||
frappe.throw(_("The selected change account {} doesn't belongs to Company {}.").format(self.account_for_change_amount, self.company))
|
frappe.throw(_("The selected change account {} doesn't belongs to Company {}.").format(self.account_for_change_amount, self.company))
|
||||||
|
|
||||||
def validate_change_amount(self):
|
def validate_change_amount(self):
|
||||||
|
|||||||
@@ -7,6 +7,8 @@ import frappe
|
|||||||
import unittest, copy, time
|
import unittest, copy, time
|
||||||
from erpnext.accounts.doctype.pos_profile.test_pos_profile import make_pos_profile
|
from erpnext.accounts.doctype.pos_profile.test_pos_profile import make_pos_profile
|
||||||
from erpnext.accounts.doctype.pos_invoice.pos_invoice import make_sales_return
|
from erpnext.accounts.doctype.pos_invoice.pos_invoice import make_sales_return
|
||||||
|
from erpnext.stock.doctype.stock_entry.stock_entry_utils import make_stock_entry
|
||||||
|
from erpnext.stock.doctype.purchase_receipt.test_purchase_receipt import make_purchase_receipt
|
||||||
|
|
||||||
class TestPOSInvoice(unittest.TestCase):
|
class TestPOSInvoice(unittest.TestCase):
|
||||||
def test_timestamp_change(self):
|
def test_timestamp_change(self):
|
||||||
@@ -221,29 +223,29 @@ class TestPOSInvoice(unittest.TestCase):
|
|||||||
from erpnext.stock.doctype.stock_entry.test_stock_entry import make_serialized_item
|
from erpnext.stock.doctype.stock_entry.test_stock_entry import make_serialized_item
|
||||||
from erpnext.stock.doctype.serial_no.serial_no import get_serial_nos
|
from erpnext.stock.doctype.serial_no.serial_no import get_serial_nos
|
||||||
|
|
||||||
se = make_serialized_item(company='_Test Company with perpetual inventory',
|
se = make_serialized_item(company='_Test Company',
|
||||||
target_warehouse="Stores - TCP1", cost_center='Main - TCP1', expense_account='Cost of Goods Sold - TCP1')
|
target_warehouse="Stores - _TC", cost_center='Main - _TC', expense_account='Cost of Goods Sold - _TC')
|
||||||
|
|
||||||
serial_nos = get_serial_nos(se.get("items")[0].serial_no)
|
serial_nos = get_serial_nos(se.get("items")[0].serial_no)
|
||||||
|
|
||||||
pos = create_pos_invoice(company='_Test Company with perpetual inventory', debit_to='Debtors - TCP1',
|
pos = create_pos_invoice(company='_Test Company', debit_to='Debtors - _TC',
|
||||||
account_for_change_amount='Cash - TCP1', warehouse='Stores - TCP1', income_account='Sales - TCP1',
|
account_for_change_amount='Cash - _TC', warehouse='Stores - _TC', income_account='Sales - _TC',
|
||||||
expense_account='Cost of Goods Sold - TCP1', cost_center='Main - TCP1',
|
expense_account='Cost of Goods Sold - _TC', cost_center='Main - _TC',
|
||||||
item=se.get("items")[0].item_code, rate=1000, do_not_save=1)
|
item=se.get("items")[0].item_code, rate=1000, do_not_save=1)
|
||||||
|
|
||||||
pos.get("items")[0].serial_no = serial_nos[0]
|
pos.get("items")[0].serial_no = serial_nos[0]
|
||||||
pos.append("payments", {'mode_of_payment': 'Bank Draft', 'account': '_Test Bank - TCP1', 'amount': 1000})
|
pos.append("payments", {'mode_of_payment': 'Bank Draft', 'account': '_Test Bank - _TC', 'amount': 1000})
|
||||||
|
|
||||||
pos.insert()
|
pos.insert()
|
||||||
pos.submit()
|
pos.submit()
|
||||||
|
|
||||||
pos2 = create_pos_invoice(company='_Test Company with perpetual inventory', debit_to='Debtors - TCP1',
|
pos2 = create_pos_invoice(company='_Test Company', debit_to='Debtors - _TC',
|
||||||
account_for_change_amount='Cash - TCP1', warehouse='Stores - TCP1', income_account='Sales - TCP1',
|
account_for_change_amount='Cash - _TC', warehouse='Stores - _TC', income_account='Sales - _TC',
|
||||||
expense_account='Cost of Goods Sold - TCP1', cost_center='Main - TCP1',
|
expense_account='Cost of Goods Sold - _TC', cost_center='Main - _TC',
|
||||||
item=se.get("items")[0].item_code, rate=1000, do_not_save=1)
|
item=se.get("items")[0].item_code, rate=1000, do_not_save=1)
|
||||||
|
|
||||||
pos2.get("items")[0].serial_no = serial_nos[0]
|
pos2.get("items")[0].serial_no = serial_nos[0]
|
||||||
pos2.append("payments", {'mode_of_payment': 'Bank Draft', 'account': '_Test Bank - TCP1', 'amount': 1000})
|
pos2.append("payments", {'mode_of_payment': 'Bank Draft', 'account': '_Test Bank - _TC', 'amount': 1000})
|
||||||
|
|
||||||
self.assertRaises(frappe.ValidationError, pos2.insert)
|
self.assertRaises(frappe.ValidationError, pos2.insert)
|
||||||
|
|
||||||
@@ -285,7 +287,7 @@ class TestPOSInvoice(unittest.TestCase):
|
|||||||
|
|
||||||
after_redeem_lp_details = get_loyalty_program_details_with_points(inv.customer, company=inv.company, loyalty_program=inv.loyalty_program)
|
after_redeem_lp_details = get_loyalty_program_details_with_points(inv.customer, company=inv.company, loyalty_program=inv.loyalty_program)
|
||||||
self.assertEqual(after_redeem_lp_details.loyalty_points, 9)
|
self.assertEqual(after_redeem_lp_details.loyalty_points, 9)
|
||||||
|
|
||||||
def test_merging_into_sales_invoice_with_discount(self):
|
def test_merging_into_sales_invoice_with_discount(self):
|
||||||
from erpnext.accounts.doctype.pos_closing_entry.test_pos_closing_entry import init_user_and_profile
|
from erpnext.accounts.doctype.pos_closing_entry.test_pos_closing_entry import init_user_and_profile
|
||||||
from erpnext.accounts.doctype.pos_invoice_merge_log.pos_invoice_merge_log import merge_pos_invoices
|
from erpnext.accounts.doctype.pos_invoice_merge_log.pos_invoice_merge_log import merge_pos_invoices
|
||||||
@@ -294,7 +296,7 @@ class TestPOSInvoice(unittest.TestCase):
|
|||||||
test_user, pos_profile = init_user_and_profile()
|
test_user, pos_profile = init_user_and_profile()
|
||||||
pos_inv = create_pos_invoice(rate=300, additional_discount_percentage=10, do_not_submit=1)
|
pos_inv = create_pos_invoice(rate=300, additional_discount_percentage=10, do_not_submit=1)
|
||||||
pos_inv.append('payments', {
|
pos_inv.append('payments', {
|
||||||
'mode_of_payment': 'Cash', 'account': 'Cash - _TC', 'amount': 300
|
'mode_of_payment': 'Cash', 'account': 'Cash - _TC', 'amount': 270
|
||||||
})
|
})
|
||||||
pos_inv.submit()
|
pos_inv.submit()
|
||||||
|
|
||||||
@@ -307,9 +309,10 @@ class TestPOSInvoice(unittest.TestCase):
|
|||||||
merge_pos_invoices()
|
merge_pos_invoices()
|
||||||
|
|
||||||
pos_inv.load_from_db()
|
pos_inv.load_from_db()
|
||||||
sales_invoice = frappe.get_doc("Sales Invoice", pos_inv.consolidated_invoice)
|
rounded_total = frappe.db.get_value("Sales Invoice", pos_inv.consolidated_invoice, "rounded_total")
|
||||||
self.assertEqual(sales_invoice.grand_total, 3500)
|
self.assertEqual(rounded_total, 3470)
|
||||||
|
frappe.set_user("Administrator")
|
||||||
|
|
||||||
def test_merging_into_sales_invoice_with_discount_and_inclusive_tax(self):
|
def test_merging_into_sales_invoice_with_discount_and_inclusive_tax(self):
|
||||||
from erpnext.accounts.doctype.pos_closing_entry.test_pos_closing_entry import init_user_and_profile
|
from erpnext.accounts.doctype.pos_closing_entry.test_pos_closing_entry import init_user_and_profile
|
||||||
from erpnext.accounts.doctype.pos_invoice_merge_log.pos_invoice_merge_log import merge_pos_invoices
|
from erpnext.accounts.doctype.pos_invoice_merge_log.pos_invoice_merge_log import merge_pos_invoices
|
||||||
@@ -348,8 +351,55 @@ class TestPOSInvoice(unittest.TestCase):
|
|||||||
merge_pos_invoices()
|
merge_pos_invoices()
|
||||||
|
|
||||||
pos_inv.load_from_db()
|
pos_inv.load_from_db()
|
||||||
sales_invoice = frappe.get_doc("Sales Invoice", pos_inv.consolidated_invoice)
|
rounded_total = frappe.db.get_value("Sales Invoice", pos_inv.consolidated_invoice, "rounded_total")
|
||||||
self.assertEqual(sales_invoice.rounded_total, 840)
|
self.assertEqual(rounded_total, 840)
|
||||||
|
frappe.set_user("Administrator")
|
||||||
|
|
||||||
|
def test_merging_with_validate_selling_price(self):
|
||||||
|
from erpnext.accounts.doctype.pos_closing_entry.test_pos_closing_entry import init_user_and_profile
|
||||||
|
from erpnext.accounts.doctype.pos_invoice_merge_log.pos_invoice_merge_log import merge_pos_invoices
|
||||||
|
|
||||||
|
if not frappe.db.get_single_value("Selling Settings", "validate_selling_price"):
|
||||||
|
frappe.db.set_value("Selling Settings", "Selling Settings", "validate_selling_price", 1)
|
||||||
|
|
||||||
|
make_purchase_receipt(item_code="_Test Item", warehouse="_Test Warehouse - _TC", qty=1, rate=300)
|
||||||
|
frappe.db.sql("delete from `tabPOS Invoice`")
|
||||||
|
test_user, pos_profile = init_user_and_profile()
|
||||||
|
pos_inv = create_pos_invoice(rate=300, do_not_submit=1)
|
||||||
|
pos_inv.append('payments', {
|
||||||
|
'mode_of_payment': 'Cash', 'account': 'Cash - _TC', 'amount': 300
|
||||||
|
})
|
||||||
|
pos_inv.append('taxes', {
|
||||||
|
"charge_type": "On Net Total",
|
||||||
|
"account_head": "_Test Account Service Tax - _TC",
|
||||||
|
"cost_center": "_Test Cost Center - _TC",
|
||||||
|
"description": "Service Tax",
|
||||||
|
"rate": 14,
|
||||||
|
'included_in_print_rate': 1
|
||||||
|
})
|
||||||
|
self.assertRaises(frappe.ValidationError, pos_inv.submit)
|
||||||
|
|
||||||
|
pos_inv2 = create_pos_invoice(rate=400, do_not_submit=1)
|
||||||
|
pos_inv2.append('payments', {
|
||||||
|
'mode_of_payment': 'Cash', 'account': 'Cash - _TC', 'amount': 400
|
||||||
|
})
|
||||||
|
pos_inv2.append('taxes', {
|
||||||
|
"charge_type": "On Net Total",
|
||||||
|
"account_head": "_Test Account Service Tax - _TC",
|
||||||
|
"cost_center": "_Test Cost Center - _TC",
|
||||||
|
"description": "Service Tax",
|
||||||
|
"rate": 14,
|
||||||
|
'included_in_print_rate': 1
|
||||||
|
})
|
||||||
|
pos_inv2.submit()
|
||||||
|
|
||||||
|
merge_pos_invoices()
|
||||||
|
|
||||||
|
pos_inv2.load_from_db()
|
||||||
|
rounded_total = frappe.db.get_value("Sales Invoice", pos_inv2.consolidated_invoice, "rounded_total")
|
||||||
|
self.assertEqual(rounded_total, 400)
|
||||||
|
frappe.set_user("Administrator")
|
||||||
|
frappe.db.set_value("Selling Settings", "Selling Settings", "validate_selling_price", 0)
|
||||||
|
|
||||||
def create_pos_invoice(**args):
|
def create_pos_invoice(**args):
|
||||||
args = frappe._dict(args)
|
args = frappe._dict(args)
|
||||||
@@ -364,8 +414,6 @@ def create_pos_invoice(**args):
|
|||||||
pos_inv.is_pos = 1
|
pos_inv.is_pos = 1
|
||||||
pos_inv.pos_profile = args.pos_profile or pos_profile.name
|
pos_inv.pos_profile = args.pos_profile or pos_profile.name
|
||||||
|
|
||||||
pos_inv.set_missing_values()
|
|
||||||
|
|
||||||
if args.posting_date:
|
if args.posting_date:
|
||||||
pos_inv.set_posting_time = 1
|
pos_inv.set_posting_time = 1
|
||||||
pos_inv.posting_date = args.posting_date or frappe.utils.nowdate()
|
pos_inv.posting_date = args.posting_date or frappe.utils.nowdate()
|
||||||
@@ -379,6 +427,8 @@ def create_pos_invoice(**args):
|
|||||||
pos_inv.conversion_rate = args.conversion_rate or 1
|
pos_inv.conversion_rate = args.conversion_rate or 1
|
||||||
pos_inv.account_for_change_amount = args.account_for_change_amount or "Cash - _TC"
|
pos_inv.account_for_change_amount = args.account_for_change_amount or "Cash - _TC"
|
||||||
|
|
||||||
|
pos_inv.set_missing_values()
|
||||||
|
|
||||||
pos_inv.append("items", {
|
pos_inv.append("items", {
|
||||||
"item_code": args.item or args.item_code or "_Test Item",
|
"item_code": args.item or args.item_code or "_Test Item",
|
||||||
"warehouse": args.warehouse or "_Test Warehouse - _TC",
|
"warehouse": args.warehouse or "_Test Warehouse - _TC",
|
||||||
|
|||||||
@@ -19,6 +19,7 @@
|
|||||||
"is_return",
|
"is_return",
|
||||||
"column_break1",
|
"column_break1",
|
||||||
"company",
|
"company",
|
||||||
|
"company_tax_id",
|
||||||
"posting_date",
|
"posting_date",
|
||||||
"posting_time",
|
"posting_time",
|
||||||
"set_posting_time",
|
"set_posting_time",
|
||||||
@@ -1941,6 +1942,13 @@
|
|||||||
"hide_seconds": 1,
|
"hide_seconds": 1,
|
||||||
"label": "Is Internal Customer",
|
"label": "Is Internal Customer",
|
||||||
"read_only": 1
|
"read_only": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fetch_from": "company.tax_id",
|
||||||
|
"fieldname": "company_tax_id",
|
||||||
|
"fieldtype": "Data",
|
||||||
|
"label": "Company Tax ID",
|
||||||
|
"read_only": 1
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"icon": "fa fa-file-text",
|
"icon": "fa fa-file-text",
|
||||||
|
|||||||
@@ -345,13 +345,14 @@ class Subscription(Document):
|
|||||||
invoice.set_taxes()
|
invoice.set_taxes()
|
||||||
|
|
||||||
# Due date
|
# Due date
|
||||||
invoice.append(
|
if self.days_until_due:
|
||||||
'payment_schedule',
|
invoice.append(
|
||||||
{
|
'payment_schedule',
|
||||||
'due_date': add_days(invoice.posting_date, cint(self.days_until_due)),
|
{
|
||||||
'invoice_portion': 100
|
'due_date': add_days(invoice.posting_date, cint(self.days_until_due)),
|
||||||
}
|
'invoice_portion': 100
|
||||||
)
|
}
|
||||||
|
)
|
||||||
|
|
||||||
# Discounts
|
# Discounts
|
||||||
if self.additional_discount_percentage:
|
if self.additional_discount_percentage:
|
||||||
|
|||||||
@@ -651,12 +651,12 @@ class TestPurchaseOrder(unittest.TestCase):
|
|||||||
make_subcontracted_item(item_code)
|
make_subcontracted_item(item_code)
|
||||||
|
|
||||||
po = create_purchase_order(item_code=item_code, qty=1,
|
po = create_purchase_order(item_code=item_code, qty=1,
|
||||||
is_subcontracted="Yes", supplier_warehouse="_Test Warehouse 1 - _TC")
|
is_subcontracted="Yes", supplier_warehouse="_Test Warehouse 1 - _TC", include_exploded_items=1)
|
||||||
|
|
||||||
name = frappe.db.get_value('BOM', {'item': item_code}, 'name')
|
name = frappe.db.get_value('BOM', {'item': item_code}, 'name')
|
||||||
bom = frappe.get_doc('BOM', name)
|
bom = frappe.get_doc('BOM', name)
|
||||||
|
|
||||||
exploded_items = sorted([d.item_code for d in bom.exploded_items])
|
exploded_items = sorted([d.item_code for d in bom.exploded_items if not d.get('sourced_by_supplier')])
|
||||||
supplied_items = sorted([d.rm_item_code for d in po.supplied_items])
|
supplied_items = sorted([d.rm_item_code for d in po.supplied_items])
|
||||||
self.assertEquals(exploded_items, supplied_items)
|
self.assertEquals(exploded_items, supplied_items)
|
||||||
|
|
||||||
@@ -664,7 +664,7 @@ class TestPurchaseOrder(unittest.TestCase):
|
|||||||
is_subcontracted="Yes", supplier_warehouse="_Test Warehouse 1 - _TC", include_exploded_items=0)
|
is_subcontracted="Yes", supplier_warehouse="_Test Warehouse 1 - _TC", include_exploded_items=0)
|
||||||
|
|
||||||
supplied_items1 = sorted([d.rm_item_code for d in po1.supplied_items])
|
supplied_items1 = sorted([d.rm_item_code for d in po1.supplied_items])
|
||||||
bom_items = sorted([d.item_code for d in bom.items])
|
bom_items = sorted([d.item_code for d in bom.items if not d.get('sourced_by_supplier')])
|
||||||
|
|
||||||
self.assertEquals(supplied_items1, bom_items)
|
self.assertEquals(supplied_items1, bom_items)
|
||||||
|
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import frappe
|
|||||||
from frappe.utils import nowdate
|
from frappe.utils import nowdate
|
||||||
from erpnext.stock.doctype.item.test_item import make_item
|
from erpnext.stock.doctype.item.test_item import make_item
|
||||||
from erpnext.templates.pages.rfq import check_supplier_has_docname_access
|
from erpnext.templates.pages.rfq import check_supplier_has_docname_access
|
||||||
from erpnext.buying.doctype.request_for_quotation.request_for_quotation import make_supplier_quotation
|
from erpnext.buying.doctype.request_for_quotation.request_for_quotation import make_supplier_quotation_from_rfq
|
||||||
from erpnext.buying.doctype.request_for_quotation.request_for_quotation import create_supplier_quotation
|
from erpnext.buying.doctype.request_for_quotation.request_for_quotation import create_supplier_quotation
|
||||||
from erpnext.crm.doctype.opportunity.test_opportunity import make_opportunity
|
from erpnext.crm.doctype.opportunity.test_opportunity import make_opportunity
|
||||||
from erpnext.crm.doctype.opportunity.opportunity import make_request_for_quotation as make_rfq
|
from erpnext.crm.doctype.opportunity.opportunity import make_request_for_quotation as make_rfq
|
||||||
@@ -22,7 +22,7 @@ class TestRequestforQuotation(unittest.TestCase):
|
|||||||
self.assertEqual(rfq.get('suppliers')[1].quote_status, 'Pending')
|
self.assertEqual(rfq.get('suppliers')[1].quote_status, 'Pending')
|
||||||
|
|
||||||
# Submit the first supplier quotation
|
# Submit the first supplier quotation
|
||||||
sq = make_supplier_quotation(rfq.name, rfq.get('suppliers')[0].supplier)
|
sq = make_supplier_quotation_from_rfq(rfq.name, for_supplier=rfq.get('suppliers')[0].supplier)
|
||||||
sq.submit()
|
sq.submit()
|
||||||
|
|
||||||
# No Quote first supplier quotation
|
# No Quote first supplier quotation
|
||||||
@@ -37,10 +37,10 @@ class TestRequestforQuotation(unittest.TestCase):
|
|||||||
def test_make_supplier_quotation(self):
|
def test_make_supplier_quotation(self):
|
||||||
rfq = make_request_for_quotation()
|
rfq = make_request_for_quotation()
|
||||||
|
|
||||||
sq = make_supplier_quotation(rfq.name, rfq.get('suppliers')[0].supplier)
|
sq = make_supplier_quotation_from_rfq(rfq.name, for_supplier=rfq.get('suppliers')[0].supplier)
|
||||||
sq.submit()
|
sq.submit()
|
||||||
|
|
||||||
sq1 = make_supplier_quotation(rfq.name, rfq.get('suppliers')[1].supplier)
|
sq1 = make_supplier_quotation_from_rfq(rfq.name, for_supplier=rfq.get('suppliers')[1].supplier)
|
||||||
sq1.submit()
|
sq1.submit()
|
||||||
|
|
||||||
self.assertEqual(sq.supplier, rfq.get('suppliers')[0].supplier)
|
self.assertEqual(sq.supplier, rfq.get('suppliers')[0].supplier)
|
||||||
@@ -62,7 +62,7 @@ class TestRequestforQuotation(unittest.TestCase):
|
|||||||
|
|
||||||
rfq = make_request_for_quotation(supplier_data=supplier_wt_appos)
|
rfq = make_request_for_quotation(supplier_data=supplier_wt_appos)
|
||||||
|
|
||||||
sq = make_supplier_quotation(rfq.name, supplier_wt_appos[0].get("supplier"))
|
sq = make_supplier_quotation_from_rfq(rfq.name, for_supplier=supplier_wt_appos[0].get("supplier"))
|
||||||
sq.submit()
|
sq.submit()
|
||||||
|
|
||||||
frappe.form_dict = frappe.local("form_dict")
|
frappe.form_dict = frappe.local("form_dict")
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
import frappe
|
import frappe
|
||||||
from frappe.utils import cint, flt, cstr, comma_or
|
from frappe.utils import cint, flt, cstr, comma_or, get_link_to_form
|
||||||
from frappe import _, throw
|
from frappe import _, throw
|
||||||
from erpnext.stock.get_item_details import get_bin_details
|
from erpnext.stock.get_item_details import get_bin_details
|
||||||
from erpnext.stock.utils import get_incoming_rate
|
from erpnext.stock.utils import get_incoming_rate
|
||||||
@@ -173,22 +173,26 @@ class SellingController(StockController):
|
|||||||
|
|
||||||
def validate_selling_price(self):
|
def validate_selling_price(self):
|
||||||
def throw_message(idx, item_name, rate, ref_rate_field):
|
def throw_message(idx, item_name, rate, ref_rate_field):
|
||||||
frappe.throw(_("""Row #{}: Selling rate for item {} is lower than its {}. Selling rate should be atleast {}""")
|
bold_net_rate = frappe.bold("net rate")
|
||||||
.format(idx, item_name, ref_rate_field, rate))
|
msg = (_("""Row #{}: Selling rate for item {} is lower than its {}. Selling {} should be atleast {}""")
|
||||||
|
.format(idx, frappe.bold(item_name), frappe.bold(ref_rate_field), bold_net_rate, frappe.bold(rate)))
|
||||||
|
msg += "<br><br>"
|
||||||
|
msg += (_("""You can alternatively disable selling price validation in {} to bypass this validation.""")
|
||||||
|
.format(get_link_to_form("Selling Settings", "Selling Settings")))
|
||||||
|
frappe.throw(msg, title=_("Invalid Selling Price"))
|
||||||
|
|
||||||
if not frappe.db.get_single_value("Selling Settings", "validate_selling_price"):
|
if not frappe.db.get_single_value("Selling Settings", "validate_selling_price"):
|
||||||
return
|
return
|
||||||
|
|
||||||
if hasattr(self, "is_return") and self.is_return:
|
if hasattr(self, "is_return") and self.is_return:
|
||||||
return
|
return
|
||||||
|
|
||||||
for it in self.get("items"):
|
for it in self.get("items"):
|
||||||
if not it.item_code:
|
if not it.item_code:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
last_purchase_rate, is_stock_item = frappe.get_cached_value("Item", it.item_code, ["last_purchase_rate", "is_stock_item"])
|
last_purchase_rate, is_stock_item = frappe.get_cached_value("Item", it.item_code, ["last_purchase_rate", "is_stock_item"])
|
||||||
last_purchase_rate_in_sales_uom = last_purchase_rate / (it.conversion_factor or 1)
|
last_purchase_rate_in_sales_uom = last_purchase_rate * (it.conversion_factor or 1)
|
||||||
if flt(it.base_rate) < flt(last_purchase_rate_in_sales_uom):
|
if flt(it.base_net_rate) < flt(last_purchase_rate_in_sales_uom):
|
||||||
throw_message(it.idx, frappe.bold(it.item_name), last_purchase_rate_in_sales_uom, "last purchase rate")
|
throw_message(it.idx, frappe.bold(it.item_name), last_purchase_rate_in_sales_uom, "last purchase rate")
|
||||||
|
|
||||||
last_valuation_rate = frappe.db.sql("""
|
last_valuation_rate = frappe.db.sql("""
|
||||||
@@ -197,8 +201,8 @@ class SellingController(StockController):
|
|||||||
ORDER BY posting_date DESC, posting_time DESC, creation DESC LIMIT 1
|
ORDER BY posting_date DESC, posting_time DESC, creation DESC LIMIT 1
|
||||||
""", (it.item_code, it.warehouse))
|
""", (it.item_code, it.warehouse))
|
||||||
if last_valuation_rate:
|
if last_valuation_rate:
|
||||||
last_valuation_rate_in_sales_uom = last_valuation_rate[0][0] / (it.conversion_factor or 1)
|
last_valuation_rate_in_sales_uom = last_valuation_rate[0][0] * (it.conversion_factor or 1)
|
||||||
if is_stock_item and flt(it.base_rate) < flt(last_valuation_rate_in_sales_uom) \
|
if is_stock_item and flt(it.base_net_rate) < flt(last_valuation_rate_in_sales_uom) \
|
||||||
and not self.get('is_internal_customer'):
|
and not self.get('is_internal_customer'):
|
||||||
throw_message(it.idx, frappe.bold(it.item_name), last_valuation_rate_in_sales_uom, "valuation rate")
|
throw_message(it.idx, frappe.bold(it.item_name), last_valuation_rate_in_sales_uom, "valuation rate")
|
||||||
|
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ from erpnext.accounts.party import get_party_account_currency
|
|||||||
from erpnext.exceptions import InvalidCurrency
|
from erpnext.exceptions import InvalidCurrency
|
||||||
from erpnext.stock.doctype.material_request.material_request import make_request_for_quotation
|
from erpnext.stock.doctype.material_request.material_request import make_request_for_quotation
|
||||||
from erpnext.buying.doctype.request_for_quotation.request_for_quotation import \
|
from erpnext.buying.doctype.request_for_quotation.request_for_quotation import \
|
||||||
make_supplier_quotation as make_quotation_from_rfq
|
make_supplier_quotation_from_rfq
|
||||||
|
|
||||||
def work():
|
def work():
|
||||||
frappe.set_user(frappe.db.get_global('demo_purchase_user'))
|
frappe.set_user(frappe.db.get_global('demo_purchase_user'))
|
||||||
@@ -44,7 +44,7 @@ def work():
|
|||||||
rfq = frappe.get_doc('Request for Quotation', rfq.name)
|
rfq = frappe.get_doc('Request for Quotation', rfq.name)
|
||||||
|
|
||||||
for supplier in rfq.suppliers:
|
for supplier in rfq.suppliers:
|
||||||
supplier_quotation = make_quotation_from_rfq(rfq.name, supplier.supplier)
|
supplier_quotation = make_supplier_quotation_from_rfq(rfq.name, for_supplier=supplier.supplier)
|
||||||
supplier_quotation.save()
|
supplier_quotation.save()
|
||||||
supplier_quotation.submit()
|
supplier_quotation.submit()
|
||||||
|
|
||||||
|
|||||||
@@ -392,6 +392,9 @@ regional_overrides = {
|
|||||||
'Italy': {
|
'Italy': {
|
||||||
'erpnext.controllers.taxes_and_totals.update_itemised_tax_data': 'erpnext.regional.italy.utils.update_itemised_tax_data',
|
'erpnext.controllers.taxes_and_totals.update_itemised_tax_data': 'erpnext.regional.italy.utils.update_itemised_tax_data',
|
||||||
'erpnext.controllers.accounts_controller.validate_regional': 'erpnext.regional.italy.utils.sales_invoice_validate',
|
'erpnext.controllers.accounts_controller.validate_regional': 'erpnext.regional.italy.utils.sales_invoice_validate',
|
||||||
|
},
|
||||||
|
'Germany': {
|
||||||
|
'erpnext.controllers.accounts_controller.validate_regional': 'erpnext.regional.germany.accounts_controller.validate_regional',
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
user_privacy_documents = [
|
user_privacy_documents = [
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
|
||||||
# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
|
# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
|
||||||
# License: GNU General Public License v3. See license.txt
|
# License: GNU General Public License v3. See license.txt
|
||||||
|
|
||||||
@@ -32,7 +33,7 @@ class HolidayList(Document):
|
|||||||
|
|
||||||
|
|
||||||
def validate_days(self):
|
def validate_days(self):
|
||||||
if self.from_date > self.to_date:
|
if getdate(self.from_date) > getdate(self.to_date):
|
||||||
throw(_("To Date cannot be before From Date"))
|
throw(_("To Date cannot be before From Date"))
|
||||||
|
|
||||||
for day in self.get("holidays"):
|
for day in self.get("holidays"):
|
||||||
|
|||||||
@@ -207,7 +207,6 @@ class TestBOM(unittest.TestCase):
|
|||||||
supplied_items = sorted([d.rm_item_code for d in po.supplied_items])
|
supplied_items = sorted([d.rm_item_code for d in po.supplied_items])
|
||||||
self.assertEquals(bom_items, supplied_items)
|
self.assertEquals(bom_items, supplied_items)
|
||||||
|
|
||||||
|
|
||||||
def get_default_bom(item_code="_Test FG Item 2"):
|
def get_default_bom(item_code="_Test FG Item 2"):
|
||||||
return frappe.db.get_value("BOM", {"item": item_code, "is_active": 1, "is_default": 1})
|
return frappe.db.get_value("BOM", {"item": item_code, "is_active": 1, "is_default": 1})
|
||||||
|
|
||||||
|
|||||||
@@ -347,8 +347,7 @@ class TestSalarySlip(unittest.TestCase):
|
|||||||
|
|
||||||
# create additional salary of 150000
|
# create additional salary of 150000
|
||||||
frappe.db.sql("""delete from `tabSalary Slip` where employee=%s""", (employee))
|
frappe.db.sql("""delete from `tabSalary Slip` where employee=%s""", (employee))
|
||||||
data["additional-1"] = create_additional_salary(employee, payroll_period, 50000)
|
data["additional-1"] = create_additional_salary(employee, payroll_period, 150000)
|
||||||
data["additional-2"] = create_additional_salary(employee, payroll_period, 100000)
|
|
||||||
data["deducted_dates"] = create_salary_slips_for_payroll_period(employee,
|
data["deducted_dates"] = create_salary_slips_for_payroll_period(employee,
|
||||||
salary_structure.name, payroll_period)
|
salary_structure.name, payroll_period)
|
||||||
|
|
||||||
|
|||||||
57
erpnext/regional/germany/accounts_controller.py
Normal file
57
erpnext/regional/germany/accounts_controller.py
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
import frappe
|
||||||
|
from frappe import _
|
||||||
|
from frappe import msgprint
|
||||||
|
|
||||||
|
|
||||||
|
REQUIRED_FIELDS = {
|
||||||
|
"Sales Invoice": [
|
||||||
|
{
|
||||||
|
"field_name": "company_address",
|
||||||
|
"regulation": "§ 14 Abs. 4 Nr. 1 UStG"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"field_name": "company_tax_id",
|
||||||
|
"regulation": "§ 14 Abs. 4 Nr. 2 UStG"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"field_name": "taxes",
|
||||||
|
"regulation": "§ 14 Abs. 4 Nr. 8 UStG",
|
||||||
|
"condition": "not exempt_from_sales_tax"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"field_name": "customer_address",
|
||||||
|
"regulation": "§ 14 Abs. 4 Nr. 1 UStG",
|
||||||
|
"condition": "base_grand_total > 250"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def validate_regional(doc):
|
||||||
|
"""Check if required fields for this document are present."""
|
||||||
|
required_fields = REQUIRED_FIELDS.get(doc.doctype)
|
||||||
|
if not required_fields:
|
||||||
|
return
|
||||||
|
|
||||||
|
meta = frappe.get_meta(doc.doctype)
|
||||||
|
field_map = {field.fieldname: field.label for field in meta.fields}
|
||||||
|
|
||||||
|
for field in required_fields:
|
||||||
|
condition = field.get("condition")
|
||||||
|
if condition and not frappe.safe_eval(condition, doc.as_dict()):
|
||||||
|
continue
|
||||||
|
|
||||||
|
field_name = field.get("field_name")
|
||||||
|
regulation = field.get("regulation")
|
||||||
|
if field_name and not doc.get(field_name):
|
||||||
|
missing(field_map.get(field_name), regulation)
|
||||||
|
|
||||||
|
|
||||||
|
def missing(field_label, regulation):
|
||||||
|
"""Notify the user that a required field is missing."""
|
||||||
|
context = 'Specific for Germany. Example: Remember to set Company Tax ID. It is required by § 14 Abs. 4 Nr. 2 UStG.'
|
||||||
|
msgprint(_('Remember to set {field_label}. It is required by {regulation}.', context=context).format(
|
||||||
|
field_label=frappe.bold(_(field_label)),
|
||||||
|
regulation=regulation
|
||||||
|
)
|
||||||
|
)
|
||||||
@@ -577,8 +577,9 @@ class Item(WebsiteGenerator):
|
|||||||
# if barcode is getting updated , the row name has to reset.
|
# if barcode is getting updated , the row name has to reset.
|
||||||
# Delete previous old row doc and re-enter row as if new to reset name in db.
|
# Delete previous old row doc and re-enter row as if new to reset name in db.
|
||||||
item_barcode.set("__islocal", True)
|
item_barcode.set("__islocal", True)
|
||||||
|
item_barcode_entry_name = item_barcode.name
|
||||||
item_barcode.name = None
|
item_barcode.name = None
|
||||||
frappe.delete_doc("Item Barcode", item_barcode.name)
|
frappe.delete_doc("Item Barcode", item_barcode_entry_name)
|
||||||
|
|
||||||
def validate_warehouse_for_reorder(self):
|
def validate_warehouse_for_reorder(self):
|
||||||
'''Validate Reorder level table for duplicate and conditional mandatory'''
|
'''Validate Reorder level table for duplicate and conditional mandatory'''
|
||||||
|
|||||||
@@ -471,7 +471,7 @@ class TestItem(unittest.TestCase):
|
|||||||
item_doc = frappe.get_doc('Item', item_code)
|
item_doc = frappe.get_doc('Item', item_code)
|
||||||
new_barcode = item_doc.append('barcodes')
|
new_barcode = item_doc.append('barcodes')
|
||||||
new_barcode.update(barcode_properties_list[0])
|
new_barcode.update(barcode_properties_list[0])
|
||||||
self.assertRaises(frappe.DuplicateEntryError, item_doc.save)
|
self.assertRaises(frappe.UniqueValidationError, item_doc.save)
|
||||||
|
|
||||||
# Add invalid barcode - should cause InvalidBarcode
|
# Add invalid barcode - should cause InvalidBarcode
|
||||||
item_doc = frappe.get_doc('Item', item_code)
|
item_doc = frappe.get_doc('Item', item_code)
|
||||||
|
|||||||
@@ -180,18 +180,15 @@ class TestPurchaseReceipt(unittest.TestCase):
|
|||||||
is_subcontracted="Yes", supplier_warehouse="_Test Warehouse 1 - _TC")
|
is_subcontracted="Yes", supplier_warehouse="_Test Warehouse 1 - _TC")
|
||||||
|
|
||||||
#stock raw materials in a warehouse before transfer
|
#stock raw materials in a warehouse before transfer
|
||||||
make_stock_entry(target="_Test Warehouse - _TC",
|
|
||||||
item_code="_Test Item Home Desktop 100", qty=1, basic_rate=100)
|
|
||||||
make_stock_entry(target="_Test Warehouse - _TC",
|
make_stock_entry(target="_Test Warehouse - _TC",
|
||||||
item_code = "Test Extra Item 1", qty=1, basic_rate=100)
|
item_code = "Test Extra Item 1", qty=1, basic_rate=100)
|
||||||
make_stock_entry(target="_Test Warehouse - _TC",
|
make_stock_entry(target="_Test Warehouse - _TC",
|
||||||
item_code = "_Test Item", qty=1, basic_rate=100)
|
item_code = "_Test FG Item", qty=1, basic_rate=100)
|
||||||
|
|
||||||
rm_items = [
|
rm_items = [
|
||||||
{
|
{
|
||||||
"item_code": item_code,
|
"item_code": item_code,
|
||||||
"rm_item_code": po.supplied_items[0].rm_item_code,
|
"rm_item_code": po.supplied_items[0].rm_item_code,
|
||||||
"item_name": "_Test Item",
|
"item_name": "_Test FG Item",
|
||||||
"qty": po.supplied_items[0].required_qty,
|
"qty": po.supplied_items[0].required_qty,
|
||||||
"warehouse": "_Test Warehouse - _TC",
|
"warehouse": "_Test Warehouse - _TC",
|
||||||
"stock_uom": "Nos"
|
"stock_uom": "Nos"
|
||||||
@@ -203,14 +200,6 @@ class TestPurchaseReceipt(unittest.TestCase):
|
|||||||
"qty": po.supplied_items[1].required_qty,
|
"qty": po.supplied_items[1].required_qty,
|
||||||
"warehouse": "_Test Warehouse - _TC",
|
"warehouse": "_Test Warehouse - _TC",
|
||||||
"stock_uom": "Nos"
|
"stock_uom": "Nos"
|
||||||
},
|
|
||||||
{
|
|
||||||
"item_code": item_code,
|
|
||||||
"rm_item_code": po.supplied_items[2].rm_item_code,
|
|
||||||
"item_name": "_Test Item Home Desktop 100",
|
|
||||||
"qty": po.supplied_items[2].required_qty,
|
|
||||||
"warehouse": "_Test Warehouse - _TC",
|
|
||||||
"stock_uom": "Nos"
|
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
rm_item_string = json.dumps(rm_items)
|
rm_item_string = json.dumps(rm_items)
|
||||||
|
|||||||
@@ -316,12 +316,12 @@ Authorized Signatory,المخول بالتوقيع,
|
|||||||
Auto Material Requests Generated,إنشاء طلب مواد تلقائي,
|
Auto Material Requests Generated,إنشاء طلب مواد تلقائي,
|
||||||
Auto Repeat,تكرار تلقائي,
|
Auto Repeat,تكرار تلقائي,
|
||||||
Auto repeat document updated,تكرار تلقائي للمستندات المحدثة,
|
Auto repeat document updated,تكرار تلقائي للمستندات المحدثة,
|
||||||
Automotive,سيارات,
|
Automotive,سيارات,متحرك بطاقة ذاتية
|
||||||
Available,متاح,
|
Available,متاح,
|
||||||
Available Leaves,المغادارت المتوفرة,
|
Available Leaves,المغادارت والاجازات المتاحة,
|
||||||
Available Qty,الكمية المتاحة,
|
Available Qty,الكمية المتاحة,
|
||||||
Available Selling,المبيعات المتاحة,
|
Available Selling,المبيعات المتاحة,
|
||||||
Available for use date is required,مطلوب متاح لتاريخ الاستخدام,
|
Available for use date is required,مطلوب تاريخ متاح للاستخدام,
|
||||||
Available slots,الفتحات المتاحة,
|
Available slots,الفتحات المتاحة,
|
||||||
Available {0},متاح {0},
|
Available {0},متاح {0},
|
||||||
Available-for-use Date should be after purchase date,يجب أن يكون التاريخ متاحًا بعد تاريخ الشراء,
|
Available-for-use Date should be after purchase date,يجب أن يكون التاريخ متاحًا بعد تاريخ الشراء,
|
||||||
@@ -331,16 +331,16 @@ Avg Daily Outgoing,متوسط الصادرات اليومية,
|
|||||||
Avg. Buying Price List Rate,متوسط قائمة أسعار الشراء,
|
Avg. Buying Price List Rate,متوسط قائمة أسعار الشراء,
|
||||||
Avg. Selling Price List Rate,متوسط قائمة أسعار البيع,
|
Avg. Selling Price List Rate,متوسط قائمة أسعار البيع,
|
||||||
Avg. Selling Rate,متوسط معدل البيع,
|
Avg. Selling Rate,متوسط معدل البيع,
|
||||||
BOM,فاتورة المواد,
|
BOM,قائمة مكونات المواد,
|
||||||
BOM Browser,BOM متصفح,
|
BOM Browser,قائمة مكونات المواد متصفح,
|
||||||
BOM No,رقم قائمة المواد,
|
BOM No,رقم قائمة مكونات المواد,
|
||||||
BOM Rate,سعر قائمة المواد,
|
BOM Rate,سعر او معدل قائمة مكونات المواد,
|
||||||
BOM Stock Report,تقرير مخزون فاتورة المواد,
|
BOM Stock Report,تقرير مخزون قائمة مكونات المواد,
|
||||||
BOM and Manufacturing Quantity are required,مطلوب، قائمة مكونات المواد و كمية التصنيع,
|
BOM and Manufacturing Quantity are required,مطلوب، قائمة مكونات المواد و كمية التصنيع,
|
||||||
BOM does not contain any stock item,فاتورة الموارد لا تحتوي على أي صنف مخزون,
|
BOM does not contain any stock item,قائمة مكونات المواد لا تحتوي على أي صنف مخزون,
|
||||||
BOM {0} does not belong to Item {1},قائمة المواد {0} لا تنتمي إلى الصنف {1},
|
BOM {0} does not belong to Item {1},قائمة مكونات المواد {0} لا تنتمي إلى الصنف {1},
|
||||||
BOM {0} must be active,فاتورة المواد {0} يجب أن تكون نشطة\n<br>\nBOM {0} must be active,
|
BOM {0} must be active,قائمة مكونات المواد {0} يجب أن تكون نشطة\n<br>\nBOM {0} must be active,
|
||||||
BOM {0} must be submitted,فاتورة المواد {0} يجب أن تكون مسجلة\n<br>\nBOM {0} must be submitted,
|
BOM {0} must be submitted,قائمة مكونات المواد {0} يجب أن تكون مسجلة\n<br>\nBOM {0} must be submitted,
|
||||||
Balance,الموازنة,
|
Balance,الموازنة,
|
||||||
Balance (Dr - Cr),الرصيد (مدين - دائن),
|
Balance (Dr - Cr),الرصيد (مدين - دائن),
|
||||||
Balance ({0}),الرصيد ({0}),
|
Balance ({0}),الرصيد ({0}),
|
||||||
@@ -389,23 +389,23 @@ Bill Date,تاريخ الفاتورة,
|
|||||||
Bill No,رقم الفاتورة,
|
Bill No,رقم الفاتورة,
|
||||||
Bill of Materials,فاتورة المواد,
|
Bill of Materials,فاتورة المواد,
|
||||||
Bill of Materials (BOM),قوائم المواد,
|
Bill of Materials (BOM),قوائم المواد,
|
||||||
Billable Hours,ساعات للفوترة,
|
Billable Hours,ساعات قابلة للفوترة,
|
||||||
Billed,توصف,
|
Billed,تمت الفوترة,
|
||||||
Billed Amount,القيمة المقدم فاتورة بها,
|
Billed Amount,القيمة المقدم فاتورة بها,
|
||||||
Billing,الفواتير,
|
Billing,الفواتير,
|
||||||
Billing Address,عنوان تقديم الفواتير,
|
Billing Address,العنوان الذي ترسل به الفواتير,
|
||||||
Billing Address is same as Shipping Address,عنوان الفواتير هو نفس عنوان الشحن,
|
Billing Address is same as Shipping Address,عنوان الفواتير هو نفس عنوان الشحن,
|
||||||
Billing Amount,قيمة الفواتير,
|
Billing Amount,قيمة الفواتير,
|
||||||
Billing Status,الحالة الفواتير,
|
Billing Status,حالة الفواتير,
|
||||||
Billing currency must be equal to either default company's currency or party account currency,يجب أن تكون عملة الفوترة مساوية لعملة الشركة الافتراضية أو عملة حساب الطرف,
|
Billing currency must be equal to either default company's currency or party account currency,يجب أن تكون عملة الفوترة مساوية لعملة الشركة الافتراضية أو عملة حساب الطرف,
|
||||||
Bills raised by Suppliers.,فواتير حولت من قبل الموردين.,
|
Bills raised by Suppliers.,فواتير حولت من قبل الموردين.,
|
||||||
Bills raised to Customers.,فواتير حولت للزبائن.,
|
Bills raised to Customers.,فواتير حولت للزبائن.,
|
||||||
Biotechnology,التكنولوجيا الحيوية,
|
Biotechnology,التكنولوجيا الحيوية,
|
||||||
Birthday Reminder,تذكير عيد ميلاد,
|
Birthday Reminder,تذكير عيد ميلاد,
|
||||||
Black,أسود,
|
Black,أسود,
|
||||||
Blanket Orders from Costumers.,أوامر بطانية من العملاء.,
|
Blanket Orders from Costumers.,أوامر شراء شاملة من العملاء.,
|
||||||
Block Invoice,حظر الفاتورة,
|
Block Invoice,حظر الفاتورة,
|
||||||
Boms,قوائم المواد,
|
Boms,قوائم مكونات المواد,
|
||||||
Bonus Payment Date cannot be a past date,لا يمكن أن يكون تاريخ الدفع المكافأ تاريخًا سابقًا,
|
Bonus Payment Date cannot be a past date,لا يمكن أن يكون تاريخ الدفع المكافأ تاريخًا سابقًا,
|
||||||
Both Trial Period Start Date and Trial Period End Date must be set,يجب تعيين كل من تاريخ بدء الفترة التجريبية وتاريخ انتهاء الفترة التجريبية,
|
Both Trial Period Start Date and Trial Period End Date must be set,يجب تعيين كل من تاريخ بدء الفترة التجريبية وتاريخ انتهاء الفترة التجريبية,
|
||||||
Both Warehouse must belong to same Company,يجب أن ينتمي المستودع إلى نفس الشركة\n<br>\nBoth Warehouse must belong to same Company,
|
Both Warehouse must belong to same Company,يجب أن ينتمي المستودع إلى نفس الشركة\n<br>\nBoth Warehouse must belong to same Company,
|
||||||
@@ -504,9 +504,9 @@ Cash In Hand,النقدية الحاضرة,
|
|||||||
Cash or Bank Account is mandatory for making payment entry,الحساب النقدي أو البنكي مطلوب لعمل مدخل بيع <br>Cash or Bank Account is mandatory for making payment entry,
|
Cash or Bank Account is mandatory for making payment entry,الحساب النقدي أو البنكي مطلوب لعمل مدخل بيع <br>Cash or Bank Account is mandatory for making payment entry,
|
||||||
Cashier Closing,إغلاق أمين الصندوق,
|
Cashier Closing,إغلاق أمين الصندوق,
|
||||||
Casual Leave,أجازة عادية,
|
Casual Leave,أجازة عادية,
|
||||||
Category,فئة,
|
Category,فئة,صنف
|
||||||
Category Name,اسم التصنيف,
|
Category Name,اسم التصنيف,
|
||||||
Caution,الحذر,
|
Caution,الحذر,تحذير
|
||||||
Central Tax,الضريبة المركزية,
|
Central Tax,الضريبة المركزية,
|
||||||
Certification,شهادة,
|
Certification,شهادة,
|
||||||
Cess,سيس,
|
Cess,سيس,
|
||||||
@@ -627,7 +627,7 @@ Cost Center with existing transactions can not be converted to ledger,مركز
|
|||||||
Cost Centers,مراكز التكلفة,
|
Cost Centers,مراكز التكلفة,
|
||||||
Cost Updated,تم تحديث التكلفة\n<br>\nCost Updated,
|
Cost Updated,تم تحديث التكلفة\n<br>\nCost Updated,
|
||||||
Cost as on,التكلفة كما في,
|
Cost as on,التكلفة كما في,
|
||||||
Cost of Delivered Items,تكلفة البنود المسلمة,
|
Cost of Delivered Items,تكلفة السلع والمواد المسلمة,
|
||||||
Cost of Goods Sold,تكلفة البضاعة المباعة,
|
Cost of Goods Sold,تكلفة البضاعة المباعة,
|
||||||
Cost of Issued Items,تكلفة المواد المصروفة,
|
Cost of Issued Items,تكلفة المواد المصروفة,
|
||||||
Cost of New Purchase,تكلفة الشراء الجديد,
|
Cost of New Purchase,تكلفة الشراء الجديد,
|
||||||
@@ -1300,7 +1300,7 @@ Insurance Start date should be less than Insurance End date,يجب أن يكون
|
|||||||
Integrated Tax,ضريبة متكاملة,
|
Integrated Tax,ضريبة متكاملة,
|
||||||
Inter-State Supplies,اللوازم بين الدول,
|
Inter-State Supplies,اللوازم بين الدول,
|
||||||
Interest Amount,مبلغ الفائدة,
|
Interest Amount,مبلغ الفائدة,
|
||||||
Interests,الإهتمامات,
|
Interests,الإهتمامات او الفوائد,
|
||||||
Intern,المتدرب,
|
Intern,المتدرب,
|
||||||
Internet Publishing,نشر على شبكة الإنترنت,
|
Internet Publishing,نشر على شبكة الإنترنت,
|
||||||
Intra-State Supplies,اللوازم داخل الدولة,
|
Intra-State Supplies,اللوازم داخل الدولة,
|
||||||
@@ -1421,13 +1421,13 @@ Lab Test UOM,اختبار مختبر أوم,
|
|||||||
Lab Tests and Vital Signs,اختبارات المختبر وعلامات حيوية,
|
Lab Tests and Vital Signs,اختبارات المختبر وعلامات حيوية,
|
||||||
Lab result datetime cannot be before testing datetime,لا يمكن أن يكون تاريخ نتيجة المختبر سابقا لتاريخ الفحص,
|
Lab result datetime cannot be before testing datetime,لا يمكن أن يكون تاريخ نتيجة المختبر سابقا لتاريخ الفحص,
|
||||||
Lab testing datetime cannot be before collection datetime,لا يمكن أن يكون وقت اختبار المختبر قبل تاريخ جمع البيانات,
|
Lab testing datetime cannot be before collection datetime,لا يمكن أن يكون وقت اختبار المختبر قبل تاريخ جمع البيانات,
|
||||||
Label,ملصق,
|
Label,ملصق,'طابع
|
||||||
Laboratory,مختبر,
|
Laboratory,مختبر,
|
||||||
Language Name,اسم اللغة,
|
Language Name,اسم اللغة,
|
||||||
Large,كبير,
|
Large,كبير,
|
||||||
Last Communication,آخر الاتصالات,
|
Last Communication,آخر الاتصالات,
|
||||||
Last Communication Date,تاريخ الاتصال الأخير,
|
Last Communication Date,تاريخ الاتصال الأخير,
|
||||||
Last Name,اسم العائلة,
|
Last Name,اسم العائلة او اللقب,
|
||||||
Last Order Amount,قيمة آخر طلب,
|
Last Order Amount,قيمة آخر طلب,
|
||||||
Last Order Date,تاريخ أخر أمر بيع,
|
Last Order Date,تاريخ أخر أمر بيع,
|
||||||
Last Purchase Price,سعر الشراء الأخير,
|
Last Purchase Price,سعر الشراء الأخير,
|
||||||
|
|||||||
|
Can't render this file because it is too large.
|
Reference in New Issue
Block a user