Merge branch 'develop'

This commit is contained in:
Anand Doshi 2015-09-30 17:23:52 +05:30
commit 185f488c51
73 changed files with 4381 additions and 5003 deletions

View File

@ -1,2 +1,2 @@
from __future__ import unicode_literals
__version__ = '6.3.2'
__version__ = '6.4.0'

View File

@ -50,20 +50,20 @@ class Account(Document):
def set_root_and_report_type(self):
if self.parent_account:
par = frappe.db.get_value("Account", self.parent_account, ["report_type", "root_type"], as_dict=1)
if par.report_type:
self.report_type = par.report_type
if par.root_type:
self.root_type = par.root_type
if self.is_group:
db_value = frappe.db.get_value("Account", self.name, ["report_type", "root_type"], as_dict=1)
if db_value:
if self.report_type != db_value.report_type:
frappe.db.sql("update `tabAccount` set report_type=%s where lft > %s and rgt < %s",
frappe.db.sql("update `tabAccount` set report_type=%s where lft > %s and rgt < %s",
(self.report_type, self.lft, self.rgt))
if self.root_type != db_value.root_type:
frappe.db.sql("update `tabAccount` set root_type=%s where lft > %s and rgt < %s",
frappe.db.sql("update `tabAccount` set root_type=%s where lft > %s and rgt < %s",
(self.root_type, self.lft, self.rgt))
def validate_root_details(self):
@ -89,11 +89,11 @@ class Account(Document):
frappe.throw(_("Account balance already in Debit, you are not allowed to set 'Balance Must Be' as 'Credit'"))
elif account_balance < 0 and self.balance_must_be == "Debit":
frappe.throw(_("Account balance already in Credit, you are not allowed to set 'Balance Must Be' as 'Debit'"))
def validate_account_currency(self):
if not self.account_currency:
self.account_currency = frappe.db.get_value("Company", self.company, "default_currency")
elif self.account_currency != frappe.db.get_value("Account", self.name, "account_currency"):
if frappe.db.get_value("GL Entry", {"account": self.name}):
frappe.throw(_("Currency can not be changed after making entries using some other currency"))
@ -207,3 +207,14 @@ def get_parent_account(doctype, txt, searchfield, start, page_len, filters):
and %s like %s order by name limit %s, %s""" %
("%s", searchfield, "%s", "%s", "%s"),
(filters["company"], "%%%s%%" % txt, start, page_len), as_list=1)
def get_account_currency(account):
"""Helper function to get account currency"""
def generator():
account_currency, company = frappe.db.get_value("Account", account, ["account_currency", "company"])
if not account_currency:
account_currency = frappe.db.get_value("Company", company, "default_currency")
return account_currency
return frappe.local_cache("account_currency", account, generator)

View File

@ -0,0 +1,90 @@
{
"country_code": "gt",
"name": "Cuentas de Guatemala",
"is_active": "Yes",
"tree": {
"Activos": {
"Activo Corriente": {
"Caja y Bancos": {},
"Cuentas por Cobrar": {},
"Impuestos por Cobrar": {
"IVA por Cobrar": {},
"Retenciones de IVA recibidas": {}
},
"Inventario": {}
},
"No Corriente": {
"Activos Fijos": {},
"Cargos Diferidos": {}
},
"root_type": "Asset"
},
"Pasivos": {
"Pasivo Corriente": {
"Proveedores": {
"Inventario Recibido pero No Cobrado": {
"account_type": "Stock Received But Not Billed"
}
},
"Impuestos por Pagar": {},
"Sueldos por Liquidar": {},
"Prestaciones": {},
"Cuentas por Pagar": {},
"Otras Cuentas por Pagar": {},
"Acreedores": {}
},
"Pasivo No Corriente": {
"Provisión para Indemnizaciones": {},
"Acreedores": {}
},
"root_type": "Liability"
},
"Patrimonio": {
"Capital": {},
"Utilidades Retenidas": {},
"Resultados del Ejercicio": {},
"root_type": "Asset"
},
"Costos": {
"Costo de Ventas": {},
"Costos Incluidos en la Valuación": {
"account_type": "Expenses Included In Valuation"
},
"Stock Adjustment": {
"account_type": "Stock Adjustment"
},
"root_type": "Expense"
},
"Gastos": {
"Gastos de Personal": {},
"Honorarios Profesionales": {},
"Servicios Básicos": {},
"Alquileres": {},
"Seguros": {},
"Mantenimiento": {},
"Depreciaciones": {},
"Gastos Diversos": {},
"root_type": "Expense"
},
"Ingresos": {
"Productos": {},
"Servicios": {},
"root_type": "Income"
},
"Otros Gastos y Productos Financieros": {
"Otros Ingresos": {
"Otros Gastos y Productos Financieros": {
"Intereses": {},
"Otros Gastos Financieros": {}
}
},
"Otros Gastos": {
"Otros Gastos y Productos Financieros": {
"Intereses": {},
"Otros Gastos Financieros": {}
}
},
"root_type": "Expense"
}
}
}

View File

@ -3,15 +3,13 @@
from __future__ import unicode_literals
import frappe
from frappe.utils import flt, fmt_money, getdate, formatdate
from frappe import _
from frappe.utils import flt, fmt_money, getdate, formatdate
from frappe.model.document import Document
class CustomerFrozen(frappe.ValidationError): pass
class InvalidCurrency(frappe.ValidationError): pass
class InvalidAccountCurrency(frappe.ValidationError): pass
from erpnext.accounts.party import validate_party_gle_currency, get_party_account_currency
from erpnext.accounts.utils import get_account_currency
from erpnext.setup.doctype.company.company import get_company_currency
from erpnext.exceptions import InvalidAccountCurrency, CustomerFrozen
class GLEntry(Document):
def validate(self):
@ -101,25 +99,26 @@ class GLEntry(Document):
if not frozen_accounts_modifier in frappe.get_roles():
if frappe.db.get_value(self.party_type, self.party, "is_frozen"):
frappe.throw("{0} {1} is frozen".format(self.party_type, self.party), CustomerFrozen)
def validate_currency(self):
company_currency = frappe.db.get_value("Company", self.company, "default_currency")
account_currency = frappe.db.get_value("Account", self.account, "account_currency") or company_currency
company_currency = get_company_currency(self.company)
account_currency = get_account_currency(self.account)
if not self.account_currency:
self.account_currency = company_currency
if account_currency != self.account_currency:
frappe.throw(_("Accounting Entry for {0} can only be made in currency: {1}")
.format(self.account, (account_currency or company_currency)), InvalidAccountCurrency)
if self.party_type and self.party:
party_account_currency = frappe.db.get_value(self.party_type, self.party, "party_account_currency") \
or company_currency
party_account_currency = get_party_account_currency(self.party_type, self.party, self.company)
if party_account_currency != self.account_currency:
frappe.throw(_("Accounting Entry for {0}: {1} can only be made in currency: {2}")
.format(self.party_type, self.party, party_account_currency), InvalidAccountCurrency)
.format(self.party_type, self.party, party_account_currency), InvalidAccountCurrency)
validate_party_gle_currency(self.party_type, self.party, self.company)
def validate_balance_type(account, adv_adj=False):
if not adv_adj and account:
@ -159,7 +158,7 @@ def update_outstanding_amt(account, party_type, party, against_voucher_type, aga
where against_voucher_type=%s and against_voucher=%s
and account = %s {0}""".format(party_condition),
(against_voucher_type, against_voucher, account))[0][0] or 0.0)
if against_voucher_type == 'Purchase Invoice':
bal = -bal
elif against_voucher_type == "Journal Entry":

View File

@ -6,7 +6,8 @@ import frappe
from frappe.utils import cstr, flt, fmt_money, formatdate
from frappe import msgprint, _, scrub
from erpnext.controllers.accounts_controller import AccountsController
from erpnext.accounts.utils import get_balance_on
from erpnext.accounts.utils import get_balance_on, get_account_currency
from erpnext.accounts.party import get_party_account_currency
from erpnext.setup.utils import get_company_currency
@ -146,7 +147,7 @@ class JournalEntry(AccountsController):
self.reference_totals = {}
self.reference_types = {}
self.reference_parties = {}
self.reference_accounts = {}
for d in self.get("accounts"):
if not d.reference_type:
@ -169,8 +170,7 @@ class JournalEntry(AccountsController):
self.reference_totals[d.reference_name] = 0.0
self.reference_totals[d.reference_name] += flt(d.get(dr_or_cr))
self.reference_types[d.reference_name] = d.reference_type
if d.party_type and d.party:
self.reference_parties[d.reference_name] = [d.party_type, d.party]
self.reference_accounts[d.reference_name] = d.account
against_voucher = frappe.db.get_value(d.reference_type, d.reference_name,
[scrub(dt) for dt in field_dict.get(d.reference_type)])
@ -196,7 +196,7 @@ class JournalEntry(AccountsController):
"""Validate totals, stopped and docstatus for orders"""
for reference_name, total in self.reference_totals.iteritems():
reference_type = self.reference_types[reference_name]
party_type, party = self.reference_parties.get(reference_name)
account = self.reference_accounts[reference_name]
if reference_type in ("Sales Order", "Purchase Order"):
order = frappe.db.get_value(reference_type, reference_name,
@ -212,8 +212,8 @@ class JournalEntry(AccountsController):
if cstr(order.status) == "Stopped":
frappe.throw(_("{0} {1} is stopped").format(reference_type, reference_name))
party_account_currency = frappe.db.get_value(party_type, party, "party_account_currency")
if party_account_currency == self.company_currency:
account_currency = get_account_currency(account)
if account_currency == self.company_currency:
voucher_total = order.base_grand_total
else:
voucher_total = order.grand_total
@ -609,8 +609,8 @@ def get_payment_entry_from_sales_order(sales_order):
jv = get_payment_entry(so)
jv.remark = 'Advance payment received against Sales Order {0}.'.format(so.name)
party_account = get_party_account(so.company, so.customer, "Customer")
party_account_currency = frappe.db.get_value("Account", party_account, "account_currency")
party_account = get_party_account("Customer", so.customer, so.company)
party_account_currency = get_account_currency(party_account)
exchange_rate = get_exchange_rate(party_account, party_account_currency, so.company)
@ -660,8 +660,8 @@ def get_payment_entry_from_purchase_order(purchase_order):
jv = get_payment_entry(po)
jv.remark = 'Advance payment made against Purchase Order {0}.'.format(po.name)
party_account = get_party_account(po.company, po.supplier, "Supplier")
party_account_currency = frappe.db.get_value("Account", party_account, "account_currency")
party_account = get_party_account("Supplier", po.supplier, po.company)
party_account_currency = get_account_currency(party_account)
exchange_rate = get_exchange_rate(party_account, party_account_currency, po.company)
@ -779,7 +779,7 @@ def get_party_account_and_balance(company, party_type, party):
frappe.msgprint(_("No Permission"), raise_exception=1)
from erpnext.accounts.party import get_party_account
account = get_party_account(company, party, party_type)
account = get_party_account(party_type, party, company)
account_balance = get_balance_on(account=account)
party_balance = get_balance_on(party_type=party_type, party=party)
@ -826,17 +826,20 @@ def get_exchange_rate(account, account_currency, company,
if account_currency != company_currency:
if reference_type in ("Sales Invoice", "Purchase Invoice") and reference_name:
exchange_rate = frappe.db.get_value(reference_type, reference_name, "conversion_rate")
elif account_details.account_type == "Bank" and \
elif account_details and account_details.account_type == "Bank" and \
((account_details.root_type == "Asset" and flt(credit) > 0) or
(account_details.root_type == "Liability" and debit)):
exchange_rate = get_average_exchange_rate(account)
if not exchange_rate:
if not exchange_rate and account_currency:
exchange_rate = get_exchange_rate(account_currency, company_currency)
else:
exchange_rate = 1
return exchange_rate
# don't return None or 0 as it is multipled with a value and that value could be lost
return exchange_rate or 1
def get_average_exchange_rate(account):
exchange_rate = 0

View File

@ -5,6 +5,7 @@ from __future__ import unicode_literals
import unittest, frappe
from frappe.utils import flt
from erpnext.accounts.utils import get_actual_expense, BudgetError, get_fiscal_year
from erpnext.exceptions import InvalidAccountCurrency
class TestJournalEntry(unittest.TestCase):
@ -166,15 +167,15 @@ class TestJournalEntry(unittest.TestCase):
existing_expense = self.get_actual_expense(posting_date)
make_journal_entry("_Test Account Cost for Goods Sold - _TC",
"_Test Bank - _TC", -existing_expense, "_Test Cost Center - _TC", submit=True)
def test_multi_currency(self):
jv = make_journal_entry("_Test Bank USD - _TC",
"_Test Bank - _TC", 100, exchange_rate=50, save=False)
jv.get("accounts")[1].credit_in_account_currency = 5000
jv.submit()
gl_entries = frappe.db.sql("""select account, account_currency, debit, credit,
gl_entries = frappe.db.sql("""select account, account_currency, debit, credit,
debit_in_account_currency, credit_in_account_currency
from `tabGL Entry` where voucher_type='Journal Entry' and voucher_no=%s
order by account asc""", jv.name, as_dict=1)
@ -197,12 +198,10 @@ class TestJournalEntry(unittest.TestCase):
"credit_in_account_currency": 5000
}
}
for field in ("account_currency", "debit", "debit_in_account_currency", "credit", "credit_in_account_currency"):
for i, gle in enumerate(gl_entries):
self.assertEquals(expected_values[gle.account][field], gle[field])
# cancel
jv.cancel()
@ -212,6 +211,40 @@ class TestJournalEntry(unittest.TestCase):
self.assertFalse(gle)
def test_disallow_change_in_account_currency_for_a_party(self):
# create jv in USD
jv = make_journal_entry("_Test Bank USD - _TC",
"_Test Receivable USD - _TC", 100, save=False)
jv.accounts[1].update({
"party_type": "Customer",
"party": "_Test Customer USD"
})
jv.submit()
# create jv in USD, but account currency in INR
jv = make_journal_entry("_Test Bank - _TC",
"_Test Receivable - _TC", 100, save=False)
jv.accounts[1].update({
"party_type": "Customer",
"party": "_Test Customer USD"
})
self.assertRaises(InvalidAccountCurrency, jv.submit)
# back in USD
jv = make_journal_entry("_Test Bank USD - _TC",
"_Test Receivable USD - _TC", 100, save=False)
jv.accounts[1].update({
"party_type": "Customer",
"party": "_Test Customer USD"
})
jv.submit()
def make_journal_entry(account1, account2, amount, cost_center=None, exchange_rate=1, save=True, submit=False):
jv = frappe.new_doc("Journal Entry")
jv.posting_date = "2013-02-14"
@ -231,7 +264,7 @@ def make_journal_entry(account1, account2, amount, cost_center=None, exchange_ra
"cost_center": cost_center,
"credit_in_account_currency": amount if amount > 0 else 0,
"debit_in_account_currency": abs(amount) if amount < 0 else 0,
exchange_rate: exchange_rate
"exchange_rate": exchange_rate
}
])
if save or submit:

View File

@ -70,7 +70,7 @@ class PaymentReconciliation(Document):
non_reconciled_invoices = []
dr_or_cr = "debit" if self.party_type == "Customer" else "credit"
cond = self.check_condition(dr_or_cr)
invoice_list = frappe.db.sql("""
select
voucher_no, voucher_type, posting_date,
@ -141,7 +141,7 @@ class PaymentReconciliation(Document):
def reconcile(self, args):
for e in self.get('payments'):
if " | " in e.invoice_number:
if e.invoice_number and " | " in e.invoice_number:
e.invoice_type, e.invoice_number = e.invoice_number.split(" | ")
self.get_invoice_entries()

View File

@ -7,6 +7,7 @@ from frappe import _, scrub
from frappe.utils import flt
from frappe.model.document import Document
import json
from erpnext.accounts.utils import get_account_currency
class PaymentTool(Document):
def make_journal_entry(self):
@ -59,7 +60,7 @@ def get_outstanding_vouchers(args):
args = json.loads(args)
party_account_currency = frappe.db.get_value("Account", args.get("party_account"), "account_currency")
party_account_currency = get_account_currency(args.get("party_account"))
company_currency = frappe.db.get_value("Company", args.get("company"), "default_currency")
if args.get("party_type") == "Customer" and args.get("received_or_paid") == "Received":
@ -112,7 +113,7 @@ def get_orders_to_be_billed(party_type, party, party_account_currency, company_c
@frappe.whitelist()
def get_against_voucher_amount(against_voucher_type, against_voucher_no, party_account, company):
party_account_currency = frappe.db.get_value("Account", party_account, "account_currency")
party_account_currency = get_account_currency(party_account)
company_currency = frappe.db.get_value("Company", company, "default_currency")
ref_field = "base_grand_total" if party_account_currency == company_currency else "grand_total"

View File

@ -10,6 +10,7 @@ import frappe.defaults
from erpnext.controllers.buying_controller import BuyingController
from erpnext.accounts.party import get_party_account, get_due_date
from erpnext.accounts.utils import get_account_currency
form_grid_templates = {
"items": "templates/form_grid/item_grid.html"
@ -66,7 +67,7 @@ class PurchaseInvoice(BuyingController):
def set_missing_values(self, for_validate=False):
if not self.credit_to:
self.credit_to = get_party_account(self.company, self.supplier, "Supplier")
self.credit_to = get_party_account("Supplier", self.supplier, self.company)
if not self.due_date:
self.due_date = get_due_date(self.posting_date, "Supplier", self.supplier, self.company)
@ -91,7 +92,7 @@ class PurchaseInvoice(BuyingController):
throw(_("Conversion rate cannot be 0 or 1"))
def validate_credit_to_acc(self):
account = frappe.db.get_value("Account", self.credit_to,
account = frappe.db.get_value("Account", self.credit_to,
["account_type", "report_type", "account_currency"], as_dict=True)
if account.report_type != "Balance Sheet":
@ -99,7 +100,7 @@ class PurchaseInvoice(BuyingController):
if self.supplier and account.account_type != "Payable":
frappe.throw(_("Credit To account must be a Payable account"))
self.party_account_currency = account.account_currency
def check_for_stopped_status(self):
@ -251,7 +252,7 @@ class PurchaseInvoice(BuyingController):
expenses_included_in_valuation = self.get_company_default("expenses_included_in_valuation")
gl_entries = []
# parent's gl entry
if self.base_grand_total:
gl_entries.append(
@ -272,10 +273,10 @@ class PurchaseInvoice(BuyingController):
valuation_tax = {}
for tax in self.get("taxes"):
if tax.category in ("Total", "Valuation and Total") and flt(tax.base_tax_amount_after_discount_amount):
account_currency = frappe.db.get_value("Account", tax.account_head, "account_currency")
account_currency = get_account_currency(tax.account_head)
dr_or_cr = "debit" if tax.add_deduct_tax == "Add" else "credit"
gl_entries.append(
self.get_gl_dict({
"account": tax.account_head,
@ -301,7 +302,7 @@ class PurchaseInvoice(BuyingController):
stock_items = self.get_stock_items()
for item in self.get("items"):
if flt(item.base_net_amount):
account_currency = frappe.db.get_value("Account", item.expense_account, "account_currency")
account_currency = get_account_currency(item.expense_account)
gl_entries.append(
self.get_gl_dict({
"account": item.expense_account,
@ -363,8 +364,8 @@ class PurchaseInvoice(BuyingController):
# writeoff account includes petty difference in the invoice amount
# and the amount that is paid
if self.write_off_account and flt(self.write_off_amount):
write_off_account_currency = frappe.db.get_value("Account", self.write_off_account, "account_currency")
write_off_account_currency = get_account_currency(self.write_off_account)
gl_entries.append(
self.get_gl_dict({
"account": self.credit_to,

View File

@ -10,7 +10,7 @@ from frappe.utils import cint
import frappe.defaults
from erpnext.stock.doctype.purchase_receipt.test_purchase_receipt import set_perpetual_inventory, \
test_records as pr_test_records
from erpnext.controllers.accounts_controller import InvalidCurrency
from erpnext.exceptions import InvalidCurrency
test_dependencies = ["Item", "Cost Center"]
test_ignore = ["Serial No"]
@ -219,7 +219,7 @@ class TestPurchaseInvoice(unittest.TestCase):
pi.load_from_db()
self.assertTrue(frappe.db.sql("""select name from `tabJournal Entry Account`
where reference_type='Purchase Invoice'
where reference_type='Purchase Invoice'
and reference_name=%s and debit_in_account_currency=300""", pi.name))
self.assertEqual(pi.outstanding_amount, 1212.30)
@ -237,17 +237,17 @@ class TestPurchaseInvoice(unittest.TestCase):
existing_purchase_cost = frappe.db.sql("""select sum(ifnull(base_net_amount, 0))
from `tabPurchase Invoice Item` where project_name = '_Test Project' and docstatus=1""")
existing_purchase_cost = existing_purchase_cost and existing_purchase_cost[0][0] or 0
pi = make_purchase_invoice(currency="USD", conversion_rate=60, project_name="_Test Project")
self.assertEqual(frappe.db.get_value("Project", "_Test Project", "total_purchase_cost"),
self.assertEqual(frappe.db.get_value("Project", "_Test Project", "total_purchase_cost"),
existing_purchase_cost + 15000)
pi1 = make_purchase_invoice(qty=10, project_name="_Test Project")
self.assertEqual(frappe.db.get_value("Project", "_Test Project", "total_purchase_cost"),
self.assertEqual(frappe.db.get_value("Project", "_Test Project", "total_purchase_cost"),
existing_purchase_cost + 15500)
pi1.cancel()
self.assertEqual(frappe.db.get_value("Project", "_Test Project", "total_purchase_cost"),
self.assertEqual(frappe.db.get_value("Project", "_Test Project", "total_purchase_cost"),
existing_purchase_cost + 15000)
pi.cancel()
@ -278,14 +278,14 @@ class TestPurchaseInvoice(unittest.TestCase):
self.assertEquals(expected_values[gle.account][1], gle.credit)
set_perpetual_inventory(0)
def test_multi_currency_gle(self):
set_perpetual_inventory(0)
pi = make_purchase_invoice(supplier="_Test Supplier USD", credit_to="_Test Payable USD - _TC",
pi = make_purchase_invoice(supplier="_Test Supplier USD", credit_to="_Test Payable USD - _TC",
currency="USD", conversion_rate=50)
gl_entries = frappe.db.sql("""select account, account_currency, debit, credit,
gl_entries = frappe.db.sql("""select account, account_currency, debit, credit,
debit_in_account_currency, credit_in_account_currency
from `tabGL Entry` where voucher_type='Purchase Invoice' and voucher_no=%s
order by account asc""", pi.name, as_dict=1)
@ -308,16 +308,16 @@ class TestPurchaseInvoice(unittest.TestCase):
"credit_in_account_currency": 0
}
}
for field in ("account_currency", "debit", "debit_in_account_currency", "credit", "credit_in_account_currency"):
for i, gle in enumerate(gl_entries):
self.assertEquals(expected_values[gle.account][field], gle[field])
# Check for valid currency
pi1 = make_purchase_invoice(supplier="_Test Supplier USD", credit_to="_Test Payable USD - _TC",
do_not_save=True)
self.assertRaises(InvalidCurrency, pi1.save)
# cancel

View File

@ -11,6 +11,7 @@ from erpnext.controllers.stock_controller import update_gl_entries_after
from frappe.model.mapper import get_mapped_doc
from erpnext.controllers.selling_controller import SellingController
from erpnext.accounts.utils import get_account_currency
form_grid_templates = {
"items": "templates/form_grid/item_grid.html"
@ -186,7 +187,7 @@ class SalesInvoice(SellingController):
pos = self.set_pos_fields(for_validate)
if not self.debit_to:
self.debit_to = get_party_account(self.company, self.customer, "Customer")
self.debit_to = get_party_account("Customer", self.customer, self.company)
if not self.due_date and self.customer:
self.due_date = get_due_date(self.posting_date, "Customer", self.customer, self.company)
@ -531,7 +532,7 @@ class SalesInvoice(SellingController):
def make_tax_gl_entries(self, gl_entries):
for tax in self.get("taxes"):
if flt(tax.base_tax_amount_after_discount_amount):
account_currency = frappe.db.get_value("Account", tax.account_head, "account_currency")
account_currency = get_account_currency(tax.account_head)
gl_entries.append(
self.get_gl_dict({
"account": tax.account_head,
@ -547,7 +548,7 @@ class SalesInvoice(SellingController):
# income account gl entries
for item in self.get("items"):
if flt(item.base_net_amount):
account_currency = frappe.db.get_value("Account", item.income_account, "account_currency")
account_currency = get_account_currency(item.income_account)
gl_entries.append(
self.get_gl_dict({
"account": item.income_account,
@ -566,7 +567,7 @@ class SalesInvoice(SellingController):
def make_pos_gl_entries(self, gl_entries):
if cint(self.is_pos) and self.cash_bank_account and self.paid_amount:
bank_account_currency = frappe.db.get_value("Account", self.cash_bank_account, "account_currency")
bank_account_currency = get_account_currency(self.cash_bank_account)
# POS, make payment entries
gl_entries.append(
self.get_gl_dict({
@ -594,7 +595,7 @@ class SalesInvoice(SellingController):
def make_write_off_gl_entry(self, gl_entries):
# write off entries, applicable if only pos
if self.write_off_account and self.write_off_amount:
write_off_account_currency = frappe.db.get_value("Account", self.write_off_account, "account_currency")
write_off_account_currency = get_account_currency(self.write_off_account)
gl_entries.append(
self.get_gl_dict({

View File

@ -7,8 +7,7 @@ import unittest, copy
from frappe.utils import nowdate, add_days, flt
from erpnext.stock.doctype.stock_entry.test_stock_entry import make_stock_entry, get_qty_after_transaction
from erpnext.stock.doctype.purchase_receipt.test_purchase_receipt import set_perpetual_inventory
from erpnext.controllers.accounts_controller import InvalidCurrency
from erpnext.accounts.doctype.gl_entry.gl_entry import InvalidAccountCurrency
from erpnext.exceptions import InvalidAccountCurrency, InvalidCurrency
class TestSalesInvoice(unittest.TestCase):
def make(self):
@ -842,13 +841,13 @@ class TestSalesInvoice(unittest.TestCase):
self.assertEquals(si.total_taxes_and_charges, 234.44)
self.assertEquals(si.base_grand_total, 859.44)
self.assertEquals(si.grand_total, 859.44)
def test_multi_currency_gle(self):
set_perpetual_inventory(0)
si = create_sales_invoice(customer="_Test Customer USD", debit_to="_Test Receivable USD - _TC",
si = create_sales_invoice(customer="_Test Customer USD", debit_to="_Test Receivable USD - _TC",
currency="USD", conversion_rate=50)
gl_entries = frappe.db.sql("""select account, account_currency, debit, credit,
gl_entries = frappe.db.sql("""select account, account_currency, debit, credit,
debit_in_account_currency, credit_in_account_currency
from `tabGL Entry` where voucher_type='Sales Invoice' and voucher_no=%s
order by account asc""", si.name, as_dict=1)
@ -871,7 +870,7 @@ class TestSalesInvoice(unittest.TestCase):
"credit_in_account_currency": 5000
}
}
for field in ("account_currency", "debit", "debit_in_account_currency", "credit", "credit_in_account_currency"):
for i, gle in enumerate(gl_entries):
self.assertEquals(expected_values[gle.account][field], gle[field])
@ -883,38 +882,38 @@ class TestSalesInvoice(unittest.TestCase):
where voucher_type='Sales Invoice' and voucher_no=%s""", si.name)
self.assertFalse(gle)
def test_invalid_currency(self):
# Customer currency = USD
# Transaction currency cannot be INR
si1 = create_sales_invoice(customer="_Test Customer USD", debit_to="_Test Receivable USD - _TC",
si1 = create_sales_invoice(customer="_Test Customer USD", debit_to="_Test Receivable USD - _TC",
do_not_save=True)
self.assertRaises(InvalidCurrency, si1.save)
# Transaction currency cannot be EUR
si2 = create_sales_invoice(customer="_Test Customer USD", debit_to="_Test Receivable USD - _TC",
si2 = create_sales_invoice(customer="_Test Customer USD", debit_to="_Test Receivable USD - _TC",
currency="EUR", conversion_rate=80, do_not_save=True)
self.assertRaises(InvalidCurrency, si2.save)
# Transaction currency only allowed in USD
si3 = create_sales_invoice(customer="_Test Customer USD", debit_to="_Test Receivable USD - _TC",
si3 = create_sales_invoice(customer="_Test Customer USD", debit_to="_Test Receivable USD - _TC",
currency="USD", conversion_rate=50)
# Party Account currency must be in USD, as there is existing GLE with USD
si4 = create_sales_invoice(customer="_Test Customer USD", debit_to="_Test Receivable - _TC",
si4 = create_sales_invoice(customer="_Test Customer USD", debit_to="_Test Receivable - _TC",
currency="USD", conversion_rate=50, do_not_submit=True)
self.assertRaises(InvalidAccountCurrency, si4.submit)
# Party Account currency must be in USD, force customer currency as there is no GLE
si3.cancel()
si5 = create_sales_invoice(customer="_Test Customer USD", debit_to="_Test Receivable - _TC",
si5 = create_sales_invoice(customer="_Test Customer USD", debit_to="_Test Receivable - _TC",
currency="USD", conversion_rate=50, do_not_submit=True)
self.assertRaises(InvalidAccountCurrency, si5.submit)
def create_sales_invoice(**args):

View File

@ -10,9 +10,9 @@ from frappe.defaults import get_user_permissions
from frappe.utils import add_days, getdate, formatdate, get_first_day, date_diff
from erpnext.utilities.doctype.address.address import get_address_display
from erpnext.utilities.doctype.contact.contact import get_contact_details
from erpnext.exceptions import InvalidAccountCurrency
class InvalidCurrency(frappe.ValidationError): pass
class InvalidAccountCurrency(frappe.ValidationError): pass
class DuplicatePartyAccountError(frappe.ValidationError): pass
@frappe.whitelist()
def get_party_details(party=None, account=None, party_type="Customer", company=None,
@ -142,7 +142,7 @@ def set_account_and_due_date(party, account, party_type, company, posting_date,
}
if party:
account = get_party_account(company, party, party_type)
account = get_party_account(party_type, party, company)
account_fieldname = "debit_to" if party_type=="Customer" else "credit_to"
@ -153,44 +153,6 @@ def set_account_and_due_date(party, account, party_type, company, posting_date,
}
return out
def validate_accounting_currency(party):
party_account_currency_in_db = frappe.db.get_value(party.doctype, party.name, "party_account_currency")
if party_account_currency_in_db != party.party_account_currency:
existing_gle = frappe.db.get_value("GL Entry", {"party_type": party.doctype,
"party": party.name}, ["name", "account_currency"], as_dict=1)
if existing_gle:
if party_account_currency_in_db:
frappe.throw(_("Accounting Currency cannot be changed, as GL Entry exists for this {0}")
.format(party.doctype), InvalidCurrency)
else:
party.party_account_currency = existing_gle.account_currency
def validate_party_account(party):
company_currency = get_company_currency()
if party.party_account_currency:
companies_with_different_currency = []
for company, currency in company_currency.items():
if currency != party.party_account_currency:
companies_with_different_currency.append(company)
for d in party.get("accounts"):
if d.company in companies_with_different_currency:
companies_with_different_currency.remove(d.company)
selected_account_currency = frappe.db.get_value("Account", d.account, "account_currency")
if selected_account_currency != party.party_account_currency:
frappe.throw(_("Account {0} is invalid, account currency must be {1}")
.format(d.account, selected_account_currency), InvalidAccountCurrency)
if companies_with_different_currency:
frappe.msgprint(_("Please mention Default {0} Account for the following companies, as accounting currency is different from company's default currency: {1}")
.format(
"Receivable" if party.doctype=="Customer" else "Payable",
"\n" + "\n".join(companies_with_different_currency)
)
)
def get_company_currency():
company_currency = frappe._dict()
for d in frappe.get_all("Company", fields=["name", "default_currency"]):
@ -199,13 +161,13 @@ def get_company_currency():
return company_currency
@frappe.whitelist()
def get_party_account(company, party, party_type):
def get_party_account(party_type, party, company):
"""Returns the account for the given `party`.
Will first search in party (Customer / Supplier) record, if not found,
will search in group (Customer Group / Supplier Type),
finally will return default."""
if not company:
frappe.throw(_("Please select company first."))
frappe.throw(_("Please select a Company"))
if party:
account = frappe.db.get_value("Party Account",
@ -223,6 +185,42 @@ def get_party_account(company, party, party_type):
return account
def get_party_account_currency(party_type, party, company):
def generator():
party_account = get_party_account(party_type, party, company)
return frappe.db.get_value("Account", party_account, "account_currency")
return frappe.local_cache("party_account_currency", (party_type, party, company), generator)
def get_party_gle_currency(party_type, party, company):
def generator():
existing_gle_currency = frappe.db.sql("""select account_currency from `tabGL Entry`
where docstatus=1 and company=%(company)s and party_type=%(party_type)s and party=%(party)s
limit 1""", { "company": company, "party_type": party_type, "party": party })
return existing_gle_currency[0][0] if existing_gle_currency else None
return frappe.local_cache("party_gle_currency", (party_type, party, company), generator)
def validate_party_gle_currency(party_type, party, company):
"""Validate party account currency with existing GL Entry's currency"""
party_account_currency = get_party_account_currency(party_type, party, company)
existing_gle_currency = get_party_gle_currency(party_type, party, company)
if existing_gle_currency and party_account_currency != existing_gle_currency:
frappe.throw(_("Accounting Entry for {0}: {1} can only be made in currency: {2}")
.format(party_type, party, existing_gle_currency), InvalidAccountCurrency)
def validate_party_accounts(doc):
companies = []
for account in doc.get("accounts"):
if account.company in companies:
frappe.throw(_("There can only be 1 Account per Company in {0} {1}").format(doc.doctype, doc.name),
DuplicatePartyAccountError)
else:
companies.append(account.company)
@frappe.whitelist()
def get_due_date(posting_date, party_type, party, company):
"""Set Due Date = Posting Date + Credit Days"""
@ -267,6 +265,9 @@ def validate_due_date(posting_date, due_date, party_type, party, company):
frappe.throw(_("Due Date cannot be before Posting Date"))
else:
default_due_date = get_due_date(posting_date, party_type, party, company)
if not default_due_date:
return
if default_due_date != posting_date and getdate(due_date) > getdate(default_due_date):
is_credit_controller = frappe.db.get_single_value("Accounts Settings", "credit_controller") in frappe.get_roles()
if is_credit_controller:

View File

@ -209,7 +209,8 @@ class ReceivablePayableReport(object):
self.gl_entries = frappe.db.sql("""select name, posting_date, account, party_type, party,
voucher_type, voucher_no, against_voucher_type, against_voucher, account_currency, remarks, {0}
from `tabGL Entry`
where docstatus < 2 and party_type=%s {1} order by posting_date, party"""
where docstatus < 2 and party_type=%s and ifnull(party, '') != '' {1}
order by posting_date, party"""
.format(select_fields, conditions), values, as_dict=True)
return self.gl_entries

View File

@ -5,6 +5,7 @@ from __future__ import unicode_literals
import frappe
from frappe.utils import flt, getdate, cstr
from frappe import _
from erpnext.accounts.utils import get_account_currency
def execute(filters=None):
account_details = {}
@ -55,7 +56,7 @@ def set_account_currency(filters):
account_currency = None
if filters.get("account"):
account_currency = frappe.db.get_value("Account", filters.account, "account_currency")
account_currency = get_account_currency(filters.account)
elif filters.get("party"):
gle_currency = frappe.db.get_value("GL Entry", {"party_type": filters.party_type,
"party": filters.party, "company": filters.company}, "account_currency")

View File

@ -0,0 +1,59 @@
// Copyright (c) 2013, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt
frappe.query_reports["Trial Balance for Party"] = {
"filters": [
{
"fieldname": "company",
"label": __("Company"),
"fieldtype": "Link",
"options": "Company",
"default": frappe.defaults.get_user_default("company"),
"reqd": 1
},
{
"fieldname": "fiscal_year",
"label": __("Fiscal Year"),
"fieldtype": "Link",
"options": "Fiscal Year",
"default": frappe.defaults.get_user_default("fiscal_year"),
"reqd": 1,
"on_change": function(query_report) {
var fiscal_year = query_report.get_values().fiscal_year;
if (!fiscal_year) {
return;
}
frappe.model.with_doc("Fiscal Year", fiscal_year, function(r) {
var fy = frappe.model.get_doc("Fiscal Year", fiscal_year);
query_report.filters_by_name.from_date.set_input(fy.year_start_date);
query_report.filters_by_name.to_date.set_input(fy.year_end_date);
query_report.trigger_refresh();
});
}
},
{
"fieldname": "from_date",
"label": __("From Date"),
"fieldtype": "Date",
"default": frappe.defaults.get_user_default("year_start_date"),
},
{
"fieldname": "to_date",
"label": __("To Date"),
"fieldtype": "Date",
"default": frappe.defaults.get_user_default("year_end_date"),
},
{
"fieldname":"party_type",
"label": __("Party Type"),
"fieldtype": "Select",
"options": ["Customer", "Supplier"],
"default": "Customer"
},
{
"fieldname": "show_zero_values",
"label": __("Show zero values"),
"fieldtype": "Check"
}
]
}

View File

@ -0,0 +1,17 @@
{
"add_total_row": 0,
"apply_user_permissions": 1,
"creation": "2015-09-22 10:28:45.762272",
"disabled": 0,
"docstatus": 0,
"doctype": "Report",
"is_standard": "Yes",
"modified": "2015-09-22 10:28:45.762272",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Trial Balance for Party",
"owner": "Administrator",
"ref_doctype": "GL Entry",
"report_name": "Trial Balance for Party",
"report_type": "Script Report"
}

View File

@ -0,0 +1,195 @@
# Copyright (c) 2013, Frappe Technologies Pvt. Ltd. and contributors
# For license information, please see license.txt
from __future__ import unicode_literals
import frappe
from frappe import _
from frappe.utils import flt, cint
from erpnext.accounts.report.trial_balance.trial_balance import validate_filters
def execute(filters=None):
validate_filters(filters)
show_party_name = is_party_name_visible(filters)
columns = get_columns(filters, show_party_name)
data = get_data(filters, show_party_name)
return columns, data
def get_data(filters, show_party_name):
party_name_field = "customer_name" if filters.get("party_type")=="Customer" else "supplier_name"
parties = frappe.get_all(filters.get("party_type"), fields = ["name", party_name_field], order_by="name")
opening_balances = get_opening_balances(filters)
balances_within_period = get_balances_within_period(filters)
data = []
total_debit, total_credit = 0, 0
for party in parties:
row = { "party": party.name }
if show_party_name:
row["party_name"] = party.get(party_name_field)
# opening
opening_debit, opening_credit = opening_balances.get(party.name, [0, 0])
row.update({
"opening_debit": opening_debit,
"opening_credit": opening_credit
})
# within period
debit, credit = balances_within_period.get(party.name, [0, 0])
row.update({
"debit": debit,
"credit": credit
})
# totals
total_debit += debit
total_credit += credit
# closing
closing_debit, closing_credit = toggle_debit_credit(opening_debit + debit, opening_credit + credit)
row.update({
"closing_debit": closing_debit,
"closing_credit": closing_credit
})
has_value = False
if (opening_debit or opening_credit or debit or credit or closing_debit or closing_credit):
has_value =True
if cint(filters.show_zero_values) or has_value:
data.append(row)
# Add total row
if total_debit or total_credit:
data.append({
"party": "'" + _("Totals") + "'",
"debit": total_debit,
"credit": total_credit
})
return data
def get_opening_balances(filters):
gle = frappe.db.sql("""
select party, sum(ifnull(debit, 0)) as opening_debit, sum(ifnull(credit, 0)) as opening_credit
from `tabGL Entry`
where company=%(company)s
and ifnull(party_type, '') = %(party_type)s and ifnull(party, '') != ''
and (posting_date < %(from_date)s or ifnull(is_opening, 'No') = 'Yes')
group by party""", {
"company": filters.company,
"from_date": filters.from_date,
"party_type": filters.party_type
}, as_dict=True)
opening = frappe._dict()
for d in gle:
opening_debit, opening_credit = toggle_debit_credit(d.opening_debit, d.opening_credit)
opening.setdefault(d.party, [opening_debit, opening_credit])
return opening
def get_balances_within_period(filters):
gle = frappe.db.sql("""
select party, sum(ifnull(debit, 0)) as debit, sum(ifnull(credit, 0)) as credit
from `tabGL Entry`
where company=%(company)s
and ifnull(party_type, '') = %(party_type)s and ifnull(party, '') != ''
and posting_date >= %(from_date)s and posting_date <= %(to_date)s
and ifnull(is_opening, 'No') = 'No'
group by party""", {
"company": filters.company,
"from_date": filters.from_date,
"to_date": filters.to_date,
"party_type": filters.party_type
}, as_dict=True)
balances_within_period = frappe._dict()
for d in gle:
balances_within_period.setdefault(d.party, [d.debit, d.credit])
return balances_within_period
def toggle_debit_credit(debit, credit):
if flt(debit) > flt(credit):
debit = flt(debit) - flt(credit)
credit = 0.0
else:
credit = flt(credit) - flt(debit)
debit = 0.0
return debit, credit
def get_columns(filters, show_party_name):
columns = [
{
"fieldname": "party",
"label": _(filters.party_type),
"fieldtype": "Link",
"options": filters.party_type,
"width": 200
},
{
"fieldname": "opening_debit",
"label": _("Opening (Dr)"),
"fieldtype": "Currency",
"width": 120
},
{
"fieldname": "opening_credit",
"label": _("Opening (Cr)"),
"fieldtype": "Currency",
"width": 120
},
{
"fieldname": "debit",
"label": _("Debit"),
"fieldtype": "Currency",
"width": 120
},
{
"fieldname": "credit",
"label": _("Credit"),
"fieldtype": "Currency",
"width": 120
},
{
"fieldname": "closing_debit",
"label": _("Closing (Dr)"),
"fieldtype": "Currency",
"width": 120
},
{
"fieldname": "closing_credit",
"label": _("Closing (Cr)"),
"fieldtype": "Currency",
"width": 120
}
]
if show_party_name:
columns.insert(1, {
"fieldname": "party_name",
"label": _(filters.party_type) + " Name",
"fieldtype": "Data",
"width": 200
})
return columns
def is_party_name_visible(filters):
show_party_name = False
if filters.get("party_type") == "Customer":
party_naming_by = frappe.db.get_single_value("Selling Settings", "cust_master_name")
else:
party_naming_by = frappe.db.get_single_value("Buying Settings", "supp_master_name")
if party_naming_by == "Naming Series":
show_party_name = True
return show_party_name

View File

@ -9,6 +9,9 @@ from frappe import throw, _
from frappe.utils import formatdate
import frappe.desk.reportview
# imported to enable erpnext.accounts.utils.get_account_currency
from erpnext.accounts.doctype.account.account import get_account_currency
class FiscalYearError(frappe.ValidationError): pass
class BudgetError(frappe.ValidationError): pass
@ -94,8 +97,8 @@ def get_balance_on(account=None, date=None, party_type=None, party=None, in_acco
select name from `tabAccount` ac where ac.name = gle.account
and ac.lft >= %s and ac.rgt <= %s
)""" % (acc.lft, acc.rgt))
# If group and currency same as company,
# If group and currency same as company,
# always return balance based on debit and credit in company currency
if acc.account_currency == frappe.db.get_value("Company", acc.company, "default_currency"):
in_account_currency = False

File diff suppressed because it is too large Load Diff

View File

@ -8,7 +8,7 @@ from frappe import msgprint, _
from frappe.model.naming import make_autoname
from erpnext.utilities.address_and_contact import load_address_and_contact
from erpnext.utilities.transaction_base import TransactionBase
from erpnext.accounts.party import validate_accounting_currency, validate_party_account
from erpnext.accounts.party import validate_party_accounts
class Supplier(TransactionBase):
def get_feed(self):
@ -45,9 +45,8 @@ class Supplier(TransactionBase):
if frappe.defaults.get_global_default('supp_master_name') == 'Naming Series':
if not self.naming_series:
msgprint(_("Series is mandatory"), raise_exception=1)
validate_accounting_currency(self)
validate_party_account(self)
validate_party_accounts(self)
def get_contacts(self,nm):
if nm:
@ -96,14 +95,14 @@ def get_dashboard_info(supplier):
billing_this_year = frappe.db.sql("""
select sum(ifnull(credit_in_account_currency, 0)) - sum(ifnull(debit_in_account_currency, 0))
from `tabGL Entry`
where voucher_type='Purchase Invoice' and party_type = 'Supplier'
and party=%s and fiscal_year = %s""",
where voucher_type='Purchase Invoice' and party_type = 'Supplier'
and party=%s and fiscal_year = %s""",
(supplier, frappe.db.get_default("fiscal_year")))
total_unpaid = frappe.db.sql("""select sum(outstanding_amount)
from `tabPurchase Invoice`
where supplier=%s and docstatus = 1""", supplier)
out["billing_this_year"] = billing_this_year[0][0] if billing_this_year else 0
out["total_unpaid"] = total_unpaid[0][0] if total_unpaid else 0

View File

@ -1,22 +1,21 @@
[
{
"doctype": "Supplier",
"supplier_name": "_Test Supplier",
"doctype": "Supplier",
"supplier_name": "_Test Supplier",
"supplier_type": "_Test Supplier Type"
},
{
"doctype": "Supplier",
"supplier_name": "_Test Supplier 1",
"doctype": "Supplier",
"supplier_name": "_Test Supplier 1",
"supplier_type": "_Test Supplier Type"
},
{
"doctype": "Supplier",
"supplier_name": "_Test Supplier USD",
"doctype": "Supplier",
"supplier_name": "_Test Supplier USD",
"supplier_type": "_Test Supplier Type",
"party_account_currency": "USD",
"accounts": [{
"company": "_Test Company",
"account": "_Test Payable USD - _TC"
}]
}
]
]

View File

@ -0,0 +1,4 @@
- Trial Balance for Customer and Supplier
- Chart of Accounts for Guatemala
- Address and Contact permissions based on Customer and Supplier
- Multi-currency Accounting: Allow Accounts in different currencies for a Customer or Supplier, if they belong to a different Company

View File

@ -187,6 +187,12 @@ def get_data():
"doctype": "GL Entry",
"is_query_report": True,
},
{
"type": "report",
"name": "Trial Balance for Party",
"doctype": "GL Entry",
"is_query_report": True,
},
{
"type": "report",
"name": "Gross Profit",

View File

@ -6,16 +6,15 @@ import frappe
from frappe import _, throw
from frappe.utils import today, flt, cint
from erpnext.setup.utils import get_company_currency, get_exchange_rate
from erpnext.accounts.utils import get_fiscal_year, validate_fiscal_year
from erpnext.accounts.utils import get_fiscal_year, validate_fiscal_year, get_account_currency
from erpnext.utilities.transaction_base import TransactionBase
from erpnext.controllers.recurring_document import convert_to_recurring, validate_recurring_document
from erpnext.controllers.sales_and_purchase_return import validate_return
from erpnext.accounts.party import get_party_account_currency, validate_party_gle_currency
from erpnext.exceptions import CustomerFrozen, InvalidCurrency
force_item_fields = ("item_group", "barcode", "brand", "stock_uom")
class CustomerFrozen(frappe.ValidationError): pass
class InvalidCurrency(frappe.ValidationError): pass
class AccountsController(TransactionBase):
def __init__(self, arg1, arg2=None):
super(AccountsController, self).__init__(arg1, arg2)
@ -169,7 +168,7 @@ class AccountsController(TransactionBase):
if item.price_list_rate:
item.rate = flt(item.price_list_rate *
(1.0 - (item.discount_percentage / 100.0)), item.precision("rate"))
(1.0 - (flt(item.discount_percentage) / 100.0)), item.precision("rate"))
def set_taxes(self):
if not self.meta.get_field("taxes"):
@ -220,7 +219,7 @@ class AccountsController(TransactionBase):
gl_dict.update(args)
if not account_currency:
account_currency = frappe.db.get_value("Account", gl_dict.account, "account_currency")
account_currency = get_account_currency(gl_dict.account)
if self.doctype != "Journal Entry":
self.validate_account_currency(gl_dict.account, account_currency)
@ -427,8 +426,7 @@ class AccountsController(TransactionBase):
if self.get("currency"):
party_type, party = self.get_party()
if party_type and party:
party_account_currency = frappe.db.get_value(party_type, party, "party_account_currency") \
or self.company_currency
party_account_currency = get_party_account_currency(party_type, party, self.company)
if party_account_currency != self.company_currency and self.currency != party_account_currency:
frappe.throw(_("Accounting Entry for {0}: {1} can only be made in currency: {2}")

View File

@ -207,10 +207,10 @@ class StatusUpdater(Document):
# update percent complete in the parent table
if args.get('target_parent_field'):
frappe.db.sql("""update `tab%(target_parent_dt)s`
set %(target_parent_field)s = (select sum(if(%(target_ref_field)s >
set %(target_parent_field)s = round((select sum(if(%(target_ref_field)s >
ifnull(%(target_field)s, 0), %(target_field)s,
%(target_ref_field)s))/sum(%(target_ref_field)s)*100
from `tab%(target_dt)s` where parent="%(name)s") %(set_modified)s
from `tab%(target_dt)s` where parent="%(name)s"), 2) %(set_modified)s
where name='%(name)s'""" % args)
# update field

View File

@ -62,7 +62,8 @@ class Newsletter(Document):
subject = self.subject, message = self.message,
reference_doctype = self.doctype, reference_name = self.name,
unsubscribe_method = "/api/method/erpnext.crm.doctype.newsletter.newsletter.unsubscribe",
unsubscribe_params = {"name": self.newsletter_list})
unsubscribe_params = {"name": self.newsletter_list},
bulk_priority = 1)
if not frappe.flags.in_test:
frappe.db.auto_commit_on_many_writes = False

View File

@ -7,8 +7,8 @@ from frappe.utils import cstr, cint
from frappe import msgprint, _
from frappe.model.mapper import get_mapped_doc
from erpnext.setup.utils import get_exchange_rate
from erpnext.utilities.transaction_base import TransactionBase
from erpnext.accounts.party import get_party_account_currency
subject_field = "title"
sender_field = "contact_email"
@ -180,9 +180,10 @@ def get_item_details(item_code):
def make_quotation(source_name, target_doc=None):
def set_missing_values(source, target):
quotation = frappe.get_doc(target)
company_currency = frappe.db.get_value("Company", quotation.company, "default_currency")
party_account_currency = frappe.db.get_value("Customer", quotation.customer, "party_account_currency")
party_account_currency = get_party_account_currency("Customer", quotation.customer, quotation.company)
if company_currency == party_account_currency:
exchange_rate = 1
else:
@ -190,7 +191,7 @@ def make_quotation(source_name, target_doc=None):
quotation.currency = party_account_currency or company_currency
quotation.conversion_rate = exchange_rate
quotation.run_method("set_missing_values")
quotation.run_method("calculate_taxes_and_totals")

7
erpnext/exceptions.py Normal file
View File

@ -0,0 +1,7 @@
from __future__ import unicode_literals
import frappe
# accounts
class CustomerFrozen(frappe.ValidationError): pass
class InvalidAccountCurrency(frappe.ValidationError): pass
class InvalidCurrency(frappe.ValidationError): pass

View File

@ -29,7 +29,7 @@ blogs.
"""
app_icon = "icon-th"
app_color = "#e74c3c"
app_version = "6.3.2"
app_version = "6.4.0"
github_link = "https://github.com/frappe/erpnext"
error_report_email = "support@erpnext.com"
@ -93,6 +93,16 @@ has_website_permission = {
"Issue": "erpnext.support.doctype.issue.issue.has_website_permission"
}
permission_query_conditions = {
"Contact": "erpnext.utilities.address_and_contact.get_permission_query_conditions_for_contact",
"Address": "erpnext.utilities.address_and_contact.get_permission_query_conditions_for_address"
}
has_permission = {
"Contact": "erpnext.utilities.address_and_contact.has_permission",
"Address": "erpnext.utilities.address_and_contact.has_permission"
}
dump_report_map = "erpnext.startup.report_data_map.data_map"
before_tests = "erpnext.setup.utils.before_tests"
@ -128,12 +138,6 @@ scheduler_events = {
"erpnext.support.doctype.issue.issue.auto_close_tickets",
"erpnext.accounts.doctype.fiscal_year.fiscal_year.auto_create_fiscal_year",
"erpnext.hr.doctype.employee.employee.send_birthday_reminders"
],
"daily_long": [
"erpnext.setup.doctype.backup_manager.backup_manager.take_backups_daily"
],
"weekly_long": [
"erpnext.setup.doctype.backup_manager.backup_manager.take_backups_weekly"
]
}

View File

@ -211,3 +211,4 @@ erpnext.patches.v6_2.remove_newsletter_duplicates
erpnext.patches.v6_2.fix_missing_default_taxes_and_lead
erpnext.patches.v5_8.tax_rule
erpnext.patches.v6_3.convert_applicable_territory
erpnext.patches.v6_4.round_status_updater_percentages

View File

@ -63,56 +63,3 @@ def execute():
where
company=%s
""", (company.default_currency, company.name))
# Set party account if default currency of party other than company's default currency
for dt in ("Customer", "Supplier"):
parties = frappe.get_all(dt, filters={"docstatus": 0})
for p in parties:
party = frappe.get_doc(dt, p.name)
party_accounts = []
for company in company_list:
# Get party GL Entries
party_gle = frappe.db.get_value("GL Entry", {"party_type": dt, "party": p.name,
"company": company.name}, ["account", "account_currency", "name"], as_dict=True)
# set party account currency
if party_gle:
party.party_account_currency = party_gle.account_currency
elif not party.party_account_currency:
party.party_account_currency = company.default_currency
# Add default receivable /payable account if not exists
# and currency is other than company currency
if party.party_account_currency and party.party_account_currency != company.default_currency:
party_account_exists_for_company = False
for d in party.get("accounts"):
if d.company == company.name:
account_currency = frappe.db.get_value("Account", d.account, "account_currency")
if account_currency == party.party_account_currency:
party_accounts.append({
"company": d.company,
"account": d.account
})
party_account_exists_for_company = True
break
if not party_account_exists_for_company:
party_account = None
if party_gle:
party_account = party_gle.account
else:
default_receivable_account_currency = frappe.db.get_value("Account",
company.default_receivable_account, "account_currency")
if default_receivable_account_currency != company.default_currency:
party_account = company.default_receivable_account
if party_account:
party_accounts.append({
"company": company.name,
"account": party_account
})
party.set("accounts", party_accounts)
party.flags.ignore_mandatory = True
party.save()

View File

@ -0,0 +1 @@
from __future__ import unicode_literals

View File

@ -0,0 +1,14 @@
from __future__ import unicode_literals
import frappe
def execute():
for doctype, fieldname in (
("Sales Order", "per_billed"),
("Sales Order", "per_delivered"),
("Delivery Note", "per_installed"),
("Purchase Order", "per_billed"),
("Purchase Order", "per_received"),
("Material Request", "per_ordered"),
):
frappe.db.sql("""update `tab{doctype}` set `{fieldname}`=round(`{fieldname}`, 2)""".format(
doctype=doctype, fieldname=fieldname))

View File

@ -1,6 +1,10 @@
frappe.listview_settings['Task'] = {
add_fields: ["project", "status", "priority", "exp_end_date"],
onload: function(listview) {
frappe.route_options = {
"status": "Open"
};
var method = "erpnext.projects.doctype.task.task.set_multiple_status";
listview.page.add_menu_item(__("Set as Open"), function() {

View File

@ -17,7 +17,7 @@ $(function() {
$.extend(shopping_cart, {
update_cart: function(opts) {
if(!full_name) {
if(!full_name || full_name==="Guest") {
if(localStorage) {
localStorage.setItem("last_visited", window.location.pathname);
localStorage.setItem("pending_add_to_cart", opts.item_code);

View File

@ -1,7 +0,0 @@
// Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
// License: GNU General Public License v3. See license.txt
// start
$(document).on('startup', function() {
console.log(__('Starting up...'));
});

File diff suppressed because it is too large Load Diff

View File

@ -7,11 +7,10 @@ from frappe.model.naming import make_autoname
from frappe import _, msgprint, throw
import frappe.defaults
from frappe.utils import flt
from frappe.desk.reportview import build_match_conditions
from erpnext.utilities.transaction_base import TransactionBase
from erpnext.utilities.address_and_contact import load_address_and_contact
from erpnext.accounts.party import validate_accounting_currency, validate_party_account
from frappe.desk.reportview import build_match_conditions
from erpnext.accounts.party import validate_party_accounts
class Customer(TransactionBase):
def get_feed(self):
@ -33,8 +32,7 @@ class Customer(TransactionBase):
def validate(self):
self.flags.is_new_doc = self.is_new()
validate_accounting_currency(self)
validate_party_account(self)
validate_party_accounts(self)
def update_lead_status(self):
if self.lead_name:
@ -197,27 +195,26 @@ def get_customer_outstanding(customer, company):
outstanding_based_on_so = flt(outstanding_based_on_so[0][0]) if outstanding_based_on_so else 0.0
# Outstanding based on Delivery Note
outstanding_based_on_dn = frappe.db.sql("""
select
sum(
(
(ifnull(dn_item.amount, 0) - ifnull((select sum(ifnull(amount, 0))
from `tabSales Invoice Item`
where ifnull(dn_detail, '') = dn_item.name and docstatus = 1), 0)
)/dn.base_net_total
)*dn.base_grand_total
)
unmarked_delivery_note_items = frappe.db.sql("""select
dn_item.name, dn_item.amount, dn.base_net_total, dn.base_grand_total
from `tabDelivery Note` dn, `tabDelivery Note Item` dn_item
where
dn.name = dn_item.parent and dn.customer=%s and dn.company=%s
dn.name = dn_item.parent
and dn.customer=%s and dn.company=%s
and dn.docstatus = 1 and dn.status != 'Stopped'
and ifnull(dn_item.against_sales_order, '') = ''
and ifnull(dn_item.against_sales_invoice, '') = ''
and ifnull(dn_item.amount, 0) > ifnull((select sum(ifnull(amount, 0))
from `tabSales Invoice Item`
where ifnull(dn_detail, '') = dn_item.name and docstatus = 1), 0)""", (customer, company))
and ifnull(dn_item.against_sales_invoice, '') = ''""", (customer, company), as_dict=True)
outstanding_based_on_dn = flt(outstanding_based_on_dn[0][0]) if outstanding_based_on_dn else 0.0
outstanding_based_on_dn = 0.0
for dn_item in unmarked_delivery_note_items:
si_amount = frappe.db.sql("""select sum(ifnull(amount, 0))
from `tabSales Invoice Item`
where dn_detail = %s and docstatus = 1""", dn_item.name)[0][0]
if flt(dn_item.amount) > flt(si_amount):
outstanding_based_on_dn += ((flt(dn_item.amount) - flt(si_amount)) \
/ dn_item.base_net_total) * dn_item.base_grand_total
return outstanding_based_on_gle + outstanding_based_on_so + outstanding_based_on_dn

View File

@ -7,9 +7,7 @@ import frappe
import unittest
from frappe.test_runner import make_test_records
from erpnext.controllers.accounts_controller import CustomerFrozen
from erpnext.accounts.party import InvalidCurrency
from erpnext.accounts.doctype.sales_invoice.test_sales_invoice import create_sales_invoice
from erpnext.exceptions import CustomerFrozen
test_ignore = ["Price List"]
@ -37,9 +35,9 @@ class TestCustomer(unittest.TestCase):
make_test_records("Address")
make_test_records("Contact")
frappe.db.set_value("Contact", "_Test Contact For _Test Customer-_Test Customer",
frappe.db.set_value("Contact", "_Test Contact For _Test Customer-_Test Customer",
"is_primary_contact", 1)
details = get_party_details("_Test Customer")
for key, value in to_check.iteritems():
@ -68,25 +66,15 @@ class TestCustomer(unittest.TestCase):
{"comment_doctype": "Customer", "comment_docname": "_Test Customer 1 Renamed"}), comment.name)
frappe.rename_doc("Customer", "_Test Customer 1 Renamed", "_Test Customer 1")
def test_freezed_customer(self):
frappe.db.set_value("Customer", "_Test Customer", "is_frozen", 1)
from erpnext.selling.doctype.sales_order.test_sales_order import make_sales_order
so = make_sales_order(do_not_save= True)
self.assertRaises(CustomerFrozen, so.save)
frappe.db.set_value("Customer", "_Test Customer", "is_frozen", 0)
so.save()
def test_multi_currency(self):
customer = frappe.get_doc("Customer", "_Test Customer USD")
create_sales_invoice(customer="_Test Customer USD", debit_to="_Test Receivable USD - _TC",
currency="USD", conversion_rate=50)
customer.party_account_currency = "EUR"
self.assertRaises(InvalidCurrency, customer.save)

View File

@ -33,7 +33,6 @@
"customer_type": "Individual",
"doctype": "Customer",
"territory": "_Test Territory",
"party_account_currency": "USD",
"accounts": [{
"company": "_Test Company",
"account": "_Test Receivable USD - _TC"

View File

@ -7,6 +7,8 @@ import frappe.permissions
import unittest
from erpnext.selling.doctype.sales_order.sales_order \
import make_material_request, make_delivery_note, make_sales_invoice, WarehouseRequired
from erpnext.accounts.doctype.journal_entry.test_journal_entry \
import make_journal_entry
from frappe.tests.test_permissions import set_user_permission_doctypes

View File

@ -1 +0,0 @@
Settings to manage automated backups to third party tools like Dropbox and Google Drive.

View File

@ -1,155 +0,0 @@
# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
# License: GNU General Public License v3. See license.txt
# SETUP:
# install pip install --upgrade dropbox
#
# Create new Dropbox App
#
# in conf.py, set oauth2 settings
# dropbox_access_key
# dropbox_access_secret
from __future__ import unicode_literals
import os
import frappe
from frappe.utils import get_request_site_address, cstr
from frappe import _
ignore_list = [".DS_Store"]
@frappe.whitelist()
def get_dropbox_authorize_url():
sess = get_dropbox_session()
request_token = sess.obtain_request_token()
return_address = get_request_site_address(True) \
+ "?cmd=erpnext.setup.doctype.backup_manager.backup_dropbox.dropbox_callback"
url = sess.build_authorize_url(request_token, return_address)
return {
"url": url,
"key": request_token.key,
"secret": request_token.secret,
}
@frappe.whitelist(allow_guest=True)
def dropbox_callback(oauth_token=None, not_approved=False):
from dropbox import client
if not not_approved:
if frappe.db.get_value("Backup Manager", None, "dropbox_access_key")==oauth_token:
allowed = 1
message = "Dropbox access allowed."
sess = get_dropbox_session()
sess.set_request_token(frappe.db.get_value("Backup Manager", None, "dropbox_access_key"),
frappe.db.get_value("Backup Manager", None, "dropbox_access_secret"))
access_token = sess.obtain_access_token()
frappe.db.set_value("Backup Manager", "Backup Manager", "dropbox_access_key", access_token.key)
frappe.db.set_value("Backup Manager", "Backup Manager", "dropbox_access_secret", access_token.secret)
frappe.db.set_value("Backup Manager", "Backup Manager", "dropbox_access_allowed", allowed)
frappe.db.set_value("Backup Manager", "Backup Manager", "send_backups_to_dropbox", 1)
dropbox_client = client.DropboxClient(sess)
try:
dropbox_client.file_create_folder("files")
except:
pass
else:
allowed = 0
message = "Illegal Access Token Please try again."
else:
allowed = 0
message = "Dropbox Access not approved."
frappe.local.message_title = "Dropbox Approval"
frappe.local.message = "<h3>%s</h3><p>Please close this window.</p>" % message
if allowed:
frappe.local.message_success = True
frappe.db.commit()
frappe.response['type'] = 'page'
frappe.response['page_name'] = 'message.html'
def backup_to_dropbox():
from dropbox import client, session
from frappe.utils.backups import new_backup
from frappe.utils import get_files_path, get_backups_path
if not frappe.db:
frappe.connect()
sess = session.DropboxSession(frappe.conf.dropbox_access_key, frappe.conf.dropbox_secret_key, "app_folder")
sess.set_token(frappe.db.get_value("Backup Manager", None, "dropbox_access_key"),
frappe.db.get_value("Backup Manager", None, "dropbox_access_secret"))
dropbox_client = client.DropboxClient(sess)
# upload database
backup = new_backup()
filename = os.path.join(get_backups_path(), os.path.basename(backup.backup_path_db))
upload_file_to_dropbox(filename, "/database", dropbox_client)
frappe.db.close()
response = dropbox_client.metadata("/files")
# upload files to files folder
did_not_upload = []
error_log = []
path = get_files_path()
for filename in os.listdir(path):
filename = cstr(filename)
if filename in ignore_list:
continue
found = False
filepath = os.path.join(path, filename)
for file_metadata in response["contents"]:
if os.path.basename(filepath) == os.path.basename(file_metadata["path"]) and os.stat(filepath).st_size == int(file_metadata["bytes"]):
found = True
break
if not found:
try:
upload_file_to_dropbox(filepath, "/files", dropbox_client)
except Exception:
did_not_upload.append(filename)
error_log.append(frappe.get_traceback())
frappe.connect()
return did_not_upload, list(set(error_log))
def get_dropbox_session():
try:
from dropbox import session
except:
frappe.msgprint(_("Please install dropbox python module"), raise_exception=1)
if not (frappe.conf.dropbox_access_key or frappe.conf.dropbox_secret_key):
frappe.throw(_("Please set Dropbox access keys in your site config"))
sess = session.DropboxSession(frappe.conf.dropbox_access_key, frappe.conf.dropbox_secret_key, "app_folder")
return sess
def upload_file_to_dropbox(filename, folder, dropbox_client):
from dropbox import rest
size = os.stat(filename).st_size
with open(filename, 'r') as f:
# if max packet size reached, use chunked uploader
max_packet_size = 4194304
if size > max_packet_size:
uploader = dropbox_client.get_chunked_uploader(f, size)
while uploader.offset < size:
try:
uploader.upload_chunked()
uploader.finish(folder + "/" + os.path.basename(filename), overwrite=True)
except rest.ErrorResponse:
pass
else:
dropbox_client.put_file(folder + "/" + os.path.basename(filename), f, overwrite=True)
if __name__=="__main__":
backup_to_dropbox()

View File

@ -1,30 +0,0 @@
<table class="table table-striped" style="max-width: 600px;">
<thead>
<tr>
<th style="width: 30%;">
{{ __("Date") }}
</th>
<th style="width: 50%;">
{{ __("File") }}
</th>
<th>
{{ __("Size") }}
</th>
</tr>
</thead>
<tbody>
{% for (var i=0; i < files.length; i++) { %}
<tr>
<td>
{{ files[i][1] }}
</td>
<td>
<a href="{{ files[i][0] }}" target="_blank">{{ files[i][0] }}</a>
</td>
<td>
{{ files[i][2] }}
</td>
</tr>
{% } %}
</tbody>
</table>

View File

@ -1,172 +0,0 @@
# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
# License: GNU General Public License v3. See license.txt
# SETUP:
# install pip install --upgrade google-api-python-client
#
# In Google API
# - create new API project
# - create new oauth2 client (create installed app type as google \
# does not support subdomains)
#
# in conf.py, set oauth2 settings
# gdrive_client_id
# gdrive_client_secret
from __future__ import unicode_literals
import httplib2
import os
import mimetypes
import frappe
import oauth2client.client
from frappe.utils import cstr
from frappe import _
from apiclient.discovery import build
from apiclient.http import MediaFileUpload
# define log config for google drive api's log messages
# basicConfig redirects log to stderr
import logging
logging.basicConfig()
@frappe.whitelist()
def get_gdrive_authorize_url():
flow = get_gdrive_flow()
authorize_url = flow.step1_get_authorize_url()
return {
"authorize_url": authorize_url,
}
def upload_files(name, mimetype, service, folder_id):
if not frappe.db:
frappe.connect()
file_name = os.path.basename(name)
media_body = MediaFileUpload(name, mimetype=mimetype, resumable=True)
body = {
'title': file_name,
'description': 'Backup File',
'mimetype': mimetype,
'parents': [{
'kind': 'drive#filelink',
'id': folder_id
}]
}
request = service.files().insert(body=body, media_body=media_body)
response = None
while response is None:
status, response = request.next_chunk()
def backup_to_gdrive():
from frappe.utils.backups import new_backup
if not frappe.db:
frappe.connect()
get_gdrive_flow()
credentials_json = frappe.db.get_value("Backup Manager", None, "gdrive_credentials")
credentials = oauth2client.client.Credentials.new_from_json(credentials_json)
http = httplib2.Http()
http = credentials.authorize(http)
drive_service = build('drive', 'v2', http=http)
# upload database
backup = new_backup()
path = os.path.join(frappe.local.site_path, "public", "backups")
filename = os.path.join(path, os.path.basename(backup.backup_path_db))
# upload files to database folder
upload_files(filename, 'application/x-gzip', drive_service,
frappe.db.get_value("Backup Manager", None, "database_folder_id"))
# upload files to files folder
did_not_upload = []
error_log = []
files_folder_id = frappe.db.get_value("Backup Manager", None, "files_folder_id")
frappe.db.close()
path = os.path.join(frappe.local.site_path, "public", "files")
for filename in os.listdir(path):
filename = cstr(filename)
found = False
filepath = os.path.join(path, filename)
ext = filename.split('.')[-1]
size = os.path.getsize(filepath)
if ext == 'gz' or ext == 'gzip':
mimetype = 'application/x-gzip'
else:
mimetype = mimetypes.types_map.get("." + ext) or "application/octet-stream"
#Compare Local File with Server File
children = drive_service.children().list(folderId=files_folder_id).execute()
for child in children.get('items', []):
file = drive_service.files().get(fileId=child['id']).execute()
if filename == file['title'] and size == int(file['fileSize']):
found = True
break
if not found:
try:
upload_files(filepath, mimetype, drive_service, files_folder_id)
except Exception, e:
did_not_upload.append(filename)
error_log.append(cstr(e))
frappe.connect()
return did_not_upload, list(set(error_log))
def get_gdrive_flow():
from oauth2client.client import OAuth2WebServerFlow
from frappe import conf
if not "gdrive_client_id" in conf:
frappe.throw(_("Please set Google Drive access keys in {0}"),format("site_config.json"))
flow = OAuth2WebServerFlow(conf.gdrive_client_id, conf.gdrive_client_secret,
"https://www.googleapis.com/auth/drive", 'urn:ietf:wg:oauth:2.0:oob')
return flow
@frappe.whitelist()
def gdrive_callback(verification_code = None):
flow = get_gdrive_flow()
if verification_code:
credentials = flow.step2_exchange(verification_code)
allowed = 1
# make folders to save id
http = httplib2.Http()
http = credentials.authorize(http)
drive_service = build('drive', 'v2', http=http)
erpnext_folder_id = create_erpnext_folder(drive_service)
database_folder_id = create_folder('database', drive_service, erpnext_folder_id)
files_folder_id = create_folder('files', drive_service, erpnext_folder_id)
frappe.db.set_value("Backup Manager", "Backup Manager", "gdrive_access_allowed", allowed)
frappe.db.set_value("Backup Manager", "Backup Manager", "database_folder_id", database_folder_id)
frappe.db.set_value("Backup Manager", "Backup Manager", "files_folder_id", files_folder_id)
final_credentials = credentials.to_json()
frappe.db.set_value("Backup Manager", "Backup Manager", "gdrive_credentials", final_credentials)
frappe.msgprint(_("Updated"))
def create_erpnext_folder(service):
if not frappe.db:
frappe.connect()
erpnext = {
'title': 'erpnext',
'mimeType': 'application/vnd.google-apps.folder'
}
erpnext = service.files().insert(body=erpnext).execute()
return erpnext['id']
def create_folder(name, service, folder_id):
database = {
'title': name,
'mimeType': 'application/vnd.google-apps.folder',
'parents': [{
'kind': 'drive#fileLink',
'id': folder_id
}]
}
database = service.files().insert(body=database).execute()
return database['id']
if __name__=="__main__":
backup_to_gdrive()

View File

@ -1,73 +0,0 @@
// Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
// License: GNU General Public License v3. See license.txt
$.extend(cur_frm.cscript, {
onload_post_render: function() {
cur_frm.fields_dict.allow_dropbox_access.$input.addClass("btn-primary");
if(cur_frm.doc.__onload && cur_frm.doc.__onload.files) {
$(frappe.render_template("backup_files_list", {files:cur_frm.doc.__onload.files}))
.appendTo(cur_frm.fields_dict.current_backups.$wrapper.empty());
}
},
refresh: function() {
cur_frm.disable_save();
},
validate_send_notifications_to: function() {
if(!cur_frm.doc.send_notifications_to) {
msgprint(__("Please specify") + ": " +
__(frappe.meta.get_label(cur_frm.doctype, "send_notifications_to")));
return false;
}
return true;
},
allow_dropbox_access: function() {
if(cur_frm.cscript.validate_send_notifications_to()) {
return frappe.call({
method: "erpnext.setup.doctype.backup_manager.backup_dropbox.get_dropbox_authorize_url",
callback: function(r) {
if(!r.exc) {
cur_frm.set_value("dropbox_access_secret", r.message.secret);
cur_frm.set_value("dropbox_access_key", r.message.key);
cur_frm.save(null, function() {
window.open(r.message.url);
});
}
}
});
}
},
allow_gdrive_access: function() {
if(cur_frm.cscript.validate_send_notifications_to()) {
return frappe.call({
method: "erpnext.setup.doctype.backup_manager.backup_googledrive.get_gdrive_authorize_url",
callback: function(r) {
if(!r.exc) {
window.open(r.message.authorize_url);
}
}
});
}
},
validate_gdrive: function() {
return frappe.call({
method: "erpnext.setup.doctype.backup_manager.backup_googledrive.gdrive_callback",
args: {
verification_code: cur_frm.doc.verification_code
},
});
},
upload_backups_to_dropbox: function() {
cur_frm.save();
},
// upload_backups_to_gdrive: function() {
// cur_frm.save();
// },
});

View File

@ -1,482 +0,0 @@
{
"allow_copy": 0,
"allow_import": 0,
"allow_rename": 0,
"creation": "2013-04-30 12:58:38",
"custom": 0,
"description": "System for managing Backups",
"docstatus": 0,
"doctype": "DocType",
"document_type": "System",
"fields": [
{
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"fieldname": "setup",
"fieldtype": "Section Break",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Download Backups",
"no_copy": 0,
"permlevel": 0,
"print_hide": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"fieldname": "current_backups",
"fieldtype": "HTML",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Current Backups",
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"description": "",
"fieldname": "sync_with_dropbox",
"fieldtype": "Section Break",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Sync with Dropbox",
"no_copy": 0,
"permlevel": 0,
"print_hide": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"fieldname": "backup_right_now",
"fieldtype": "Button",
"hidden": 1,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Backup Right Now",
"no_copy": 0,
"permlevel": 0,
"print_hide": 0,
"read_only": 1,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"fieldname": "send_backups_to_dropbox",
"fieldtype": "Check",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Send Backups to Dropbox",
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"depends_on": "send_backups_to_dropbox",
"description": "Note: Backups and files are not deleted from Dropbox, you will have to delete them manually.",
"fieldname": "upload_backups_to_dropbox",
"fieldtype": "Select",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Upload Backups to Dropbox",
"no_copy": 0,
"options": "Never\nWeekly\nDaily",
"permlevel": 0,
"print_hide": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"depends_on": "send_backups_to_dropbox",
"description": "Email ids separated by commas.",
"fieldname": "send_notifications_to",
"fieldtype": "Data",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Send Notifications To",
"no_copy": 0,
"permlevel": 0,
"print_hide": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"fieldname": "dropbox_access_key",
"fieldtype": "Data",
"hidden": 1,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Dropbox Access Key",
"no_copy": 0,
"permlevel": 0,
"print_hide": 0,
"read_only": 1,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"fieldname": "dropbox_access_secret",
"fieldtype": "Data",
"hidden": 1,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Dropbox Access Secret",
"no_copy": 0,
"permlevel": 0,
"print_hide": 0,
"read_only": 1,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"fieldname": "dropbox_access_allowed",
"fieldtype": "Check",
"hidden": 1,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Dropbox Access Allowed",
"no_copy": 0,
"permlevel": 0,
"print_hide": 0,
"read_only": 1,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"depends_on": "send_backups_to_dropbox",
"fieldname": "allow_dropbox_access",
"fieldtype": "Button",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Allow Dropbox Access",
"no_copy": 0,
"permlevel": 0,
"print_hide": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"description": "Note: Backups and files are not deleted from Google Drive, you will have to delete them manually.",
"fieldname": "sync_with_gdrive",
"fieldtype": "Section Break",
"hidden": 1,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Sync with Google Drive",
"no_copy": 0,
"permlevel": 0,
"print_hide": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"fieldname": "upload_backups_to_gdrive",
"fieldtype": "Select",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Upload Backups to Google Drive",
"no_copy": 0,
"options": "Never\nDaily\nWeekly",
"permlevel": 0,
"print_hide": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"fieldname": "allow_gdrive_access",
"fieldtype": "Button",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Allow Google Drive Access",
"no_copy": 0,
"permlevel": 0,
"print_hide": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"fieldname": "verification_code",
"fieldtype": "Data",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Enter Verification Code",
"no_copy": 0,
"permlevel": 0,
"print_hide": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"fieldname": "validate_gdrive",
"fieldtype": "Button",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Validate",
"no_copy": 0,
"permlevel": 0,
"print_hide": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"fieldname": "gdrive_access_allowed",
"fieldtype": "Check",
"hidden": 1,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Google Drive Access Allowed",
"no_copy": 0,
"permlevel": 0,
"print_hide": 0,
"read_only": 1,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"fieldname": "gdrive_credentials",
"fieldtype": "Text",
"hidden": 1,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Credentials",
"no_copy": 0,
"permlevel": 0,
"print_hide": 0,
"read_only": 1,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"fieldname": "database_folder_id",
"fieldtype": "Data",
"hidden": 1,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Database Folder ID",
"no_copy": 0,
"permlevel": 0,
"print_hide": 0,
"read_only": 1,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"fieldname": "files_folder_id",
"fieldtype": "Data",
"hidden": 1,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Files Folder ID",
"no_copy": 0,
"permlevel": 0,
"print_hide": 0,
"read_only": 1,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
}
],
"hide_heading": 0,
"hide_toolbar": 0,
"icon": "icon-cloud-upload",
"idx": 1,
"in_create": 0,
"in_dialog": 0,
"is_submittable": 0,
"issingle": 1,
"istable": 0,
"modified": "2015-05-26 04:54:10.193573",
"modified_by": "Administrator",
"module": "Setup",
"name": "Backup Manager",
"owner": "Administrator",
"permissions": [
{
"amend": 0,
"apply_user_permissions": 0,
"cancel": 0,
"create": 1,
"delete": 0,
"email": 1,
"export": 0,
"if_owner": 0,
"import": 0,
"permlevel": 0,
"print": 1,
"read": 1,
"report": 0,
"role": "System Manager",
"set_user_permissions": 0,
"share": 1,
"submit": 0,
"write": 1
}
],
"read_only": 0,
"read_only_onload": 0
}

View File

@ -1,102 +0,0 @@
# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
# License: GNU General Public License v3. See license.txt
# For license information, please see license.txt
from __future__ import unicode_literals
from frappe.utils import get_site_path, cint, split_emails
from frappe.utils.data import convert_utc_to_user_timezone
import os
import datetime
import frappe
from frappe.model.document import Document
class BackupManager(Document):
def onload(self):
self.set_onload("files", get_files())
def get_files():
def get_time(path):
dt = os.path.getmtime(path)
return convert_utc_to_user_timezone(datetime.datetime.utcfromtimestamp(dt)).strftime('%Y-%m-%d %H:%M')
def get_size(path):
size = os.path.getsize(path)
if size > 1048576:
return "{0:.1f}M".format(float(size) / 1048576)
else:
return "{0:.1f}K".format(float(size) / 1024)
path = get_site_path('private', 'backups')
files = [x for x in os.listdir(path) if os.path.isfile(os.path.join(path, x))]
files = [('/backups/' + _file,
get_time(os.path.join(path, _file)),
get_size(os.path.join(path, _file))) for _file in files]
return files
def take_backups_daily():
take_backups_if("Daily")
def take_backups_weekly():
take_backups_if("Weekly")
def take_backups_if(freq):
if cint(frappe.db.get_value("Backup Manager", None, "send_backups_to_dropbox")):
if frappe.db.get_value("Backup Manager", None, "upload_backups_to_dropbox")==freq:
take_backups_dropbox()
# if frappe.db.get_value("Backup Manager", None, "upload_backups_to_gdrive")==freq:
# take_backups_gdrive()
@frappe.whitelist()
def take_backups_dropbox():
did_not_upload, error_log = [], []
try:
from erpnext.setup.doctype.backup_manager.backup_dropbox import backup_to_dropbox
did_not_upload, error_log = backup_to_dropbox()
if did_not_upload: raise Exception
send_email(True, "Dropbox")
except Exception:
file_and_error = [" - ".join(f) for f in zip(did_not_upload, error_log)]
error_message = ("\n".join(file_and_error) + "\n" + frappe.get_traceback())
frappe.errprint(error_message)
send_email(False, "Dropbox", error_message)
#backup to gdrive
@frappe.whitelist()
def take_backups_gdrive():
did_not_upload, error_log = [], []
try:
from erpnext.setup.doctype.backup_manager.backup_googledrive import backup_to_gdrive
did_not_upload, error_log = backup_to_gdrive()
if did_not_upload: raise Exception
send_email(True, "Google Drive")
except Exception:
file_and_error = [" - ".join(f) for f in zip(did_not_upload, error_log)]
error_message = ("\n".join(file_and_error) + "\n" + frappe.get_traceback())
frappe.errprint(error_message)
send_email(False, "Google Drive", error_message)
def send_email(success, service_name, error_status=None):
if success:
subject = "Backup Upload Successful"
message ="""<h3>Backup Uploaded Successfully</h3><p>Hi there, this is just to inform you
that your backup was successfully uploaded to your %s account. So relax!</p>
""" % service_name
else:
subject = "[Warning] Backup Upload Failed"
message ="""<h3>Backup Upload Failed</h3><p>Oops, your automated backup to %s
failed.</p>
<p>Error message: %s</p>
<p>Please contact your system manager for more information.</p>
""" % (service_name, error_status)
if not frappe.db:
frappe.connect()
recipients = split_emails(frappe.db.get_value("Backup Manager", None, "send_notifications_to"))
frappe.sendmail(recipients=recipients, subject=subject, message=message)

View File

@ -46,13 +46,13 @@ class Company(Document):
if for_company != self.name:
frappe.throw(_("Account {0} does not belong to company: {1}")
.format(self.get(field), self.name))
def validate_currency(self):
self.previous_default_currency = frappe.db.get_value("Company", self.name, "default_currency")
if self.default_currency and self.previous_default_currency and \
self.default_currency != self.previous_default_currency and \
self.check_if_transactions_exist():
frappe.throw(_("Cannot change company's default currency, because there are existing transactions. Transactions must be cancelled to change the default currency."))
frappe.throw(_("Cannot change company's default currency, because there are existing transactions. Transactions must be cancelled to change the default currency."))
def on_update(self):
if not frappe.db.sql("""select name from tabAccount
@ -208,7 +208,7 @@ class Company(Document):
# clear default accounts, warehouses from item
if warehouses:
for f in ["default_warehouse", "website_warehouse"]:
frappe.db.sql("""update tabItem set %s=NULL where %s in (%s)"""
% (f, f, ', '.join(['%s']*len(warehouses))), tuple(warehouses))
@ -257,3 +257,7 @@ def get_name_with_abbr(name, company):
parts.append(company_abbr)
return " - ".join(parts)
def get_company_currency(company):
return frappe.local_cache("company_currency", company,
lambda: frappe.db.get_value("Company", company, "default_currency"))

View File

@ -84,8 +84,7 @@ class EmailDigest(Document):
common_msg)
if msg_for_this_receipient:
frappe.sendmail(recipients=user_id,
subject="[ERPNext] [{frequency} Digest] {name}".format(
frequency=self.frequency, name=self.name),
subject="{frequency} Digest".format(frequency=self.frequency),
message=msg_for_this_receipient, bulk=True)
def get_digest_msg(self):

View File

@ -69,12 +69,13 @@ class NamingSeries(Document):
# update in property setter
prop_dict = {'options': "\n".join(options), 'default': default}
for prop in prop_dict:
ps_exists = frappe.db.sql("""SELECT name FROM `tabProperty Setter`
WHERE doc_type = %s AND field_name = 'naming_series'
AND property = %s""", (doctype, prop))
ps_exists = frappe.db.get_value("Property Setter",
{"field_name": 'naming_series', 'doc_type': doctype, 'property': prop})
if ps_exists:
ps = frappe.get_doc('Property Setter', ps_exists[0][0])
ps = frappe.get_doc('Property Setter', ps_exists)
ps.value = prop_dict[prop]
ps.save()
else:

View File

@ -11,7 +11,7 @@ default_mail_footer = """<div style="padding: 7px; text-align: right; color: #88
def after_install():
frappe.get_doc({'doctype': "Role", "role_name": "Analytics"}).insert()
set_single_defaults()
frappe.db.set_default('desktop:home_page', 'setup-wizard')
frappe.db.set_default('desktop:home_page', 'setup-wizard');
feature_setup()
from erpnext.setup.page.setup_wizard.setup_wizard import add_all_roles_to
add_all_roles_to("Administrator")

View File

@ -2,7 +2,7 @@ frappe.provide("erpnext.wiz");
frappe.pages['setup-wizard'].on_page_load = function(wrapper) {
if(sys_defaults.company) {
frappe.set_route("desktop");
frappe.set_route("desk-home");
return;
}
$(".navbar:first").toggle(false);

View File

@ -92,8 +92,10 @@ def setup_account(args=None):
if args.get("add_sample_data"):
try:
make_sample_data()
frappe.clear_cache()
except FiscalYearError:
pass
except:
if args:
traceback = frappe.get_traceback()

View File

@ -10,6 +10,7 @@ from frappe import _
import frappe.defaults
from erpnext.controllers.buying_controller import BuyingController
from erpnext.accounts.utils import get_account_currency
form_grid_templates = {
"items": "templates/form_grid/item_grid.html"
@ -307,9 +308,9 @@ class PurchaseReceipt(BuyingController):
val_rate_db_precision = 6 if cint(d.precision("valuation_rate")) <= 6 else 9
# warehouse account
stock_value_diff = flt(flt(d.valuation_rate, val_rate_db_precision) * flt(d.qty)
stock_value_diff = flt(flt(d.valuation_rate, val_rate_db_precision) * flt(d.qty)
* flt(d.conversion_factor), d.precision("base_net_amount"))
gl_entries.append(self.get_gl_dict({
"account": warehouse_account[d.warehouse]["name"],
"against": stock_rbnb,
@ -319,7 +320,7 @@ class PurchaseReceipt(BuyingController):
}, warehouse_account[d.warehouse]["account_currency"]))
# stock received but not billed
stock_rbnb_currency = frappe.db.get_value("Account", stock_rbnb, "account_currency")
stock_rbnb_currency = get_account_currency(stock_rbnb)
gl_entries.append(self.get_gl_dict({
"account": stock_rbnb,
"against": warehouse_account[d.warehouse]["name"],

View File

@ -241,7 +241,6 @@ class StockEntry(StockController):
self.set_basic_rate(force)
self.distribute_additional_costs()
self.update_valuation_rate()
self.validate_valuation_rate()
self.set_total_incoming_outgoing_value()
self.set_total_amount()
@ -299,19 +298,6 @@ class StockEntry(StockController):
d.valuation_rate = flt(flt(d.basic_rate) + flt(d.additional_cost) / flt(d.transfer_qty),
d.precision("valuation_rate"))
def validate_valuation_rate(self):
if self.purpose in ["Manufacture", "Repack"]:
valuation_at_source, valuation_at_target = 0, 0
for d in self.get("items"):
if d.s_warehouse and not d.t_warehouse:
valuation_at_source += flt(d.amount)
if d.t_warehouse and not d.s_warehouse:
valuation_at_target += flt(d.amount)
if valuation_at_target + 0.001 < valuation_at_source:
frappe.throw(_("Total valuation ({0}) for manufactured or repacked item(s) can not be less than total valuation of raw materials ({1})")
.format(valuation_at_target, valuation_at_source))
def set_total_incoming_outgoing_value(self):
self.total_incoming_value = self.total_outgoing_value = 0.0
for d in self.get("items"):

View File

@ -286,7 +286,7 @@
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 1,
"print_hide": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 0,
@ -309,7 +309,7 @@
"options": "image",
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide": 1,
"read_only": 0,
"report_hide": 0,
"reqd": 0,
@ -909,7 +909,7 @@
"is_submittable": 0,
"issingle": 0,
"istable": 1,
"modified": "2015-08-27 03:30:49.875635",
"modified": "2015-09-30 02:11:55.081524",
"modified_by": "Administrator",
"module": "Stock",
"name": "Stock Entry Detail",

View File

@ -200,7 +200,8 @@ def get_default_expense_account(args, item):
def get_default_cost_center(args, item):
return (frappe.db.get_value("Project", args.get("project_name"), "cost_center")
or (item.selling_cost_center if args.get("transaction_type") == "selling" else item.buying_cost_center)
or frappe.db.get_value("Item Group", item.item_group, "default_cost_center"))
or frappe.db.get_value("Item Group", item.item_group, "default_cost_center")
or args.get("cost_center"))
def get_price_list_rate(args, item_doc, out):
meta = frappe.get_meta(args.parenttype)

View File

@ -597,7 +597,7 @@
"is_submittable": 0,
"issingle": 0,
"istable": 0,
"modified": "2015-09-07 15:51:26",
"modified": "2015-09-24 06:54:33.383186",
"modified_by": "Administrator",
"module": "Support",
"name": "Issue",
@ -605,7 +605,7 @@
"permissions": [
{
"amend": 0,
"apply_user_permissions": 0,
"apply_user_permissions": 1,
"cancel": 0,
"create": 1,
"delete": 0,

View File

@ -1,6 +1,10 @@
frappe.listview_settings['Issue'] = {
colwidths: {"subject": 6},
onload: function(listview) {
frappe.route_options = {
"status": "Open"
};
var method = "erpnext.support.doctype.issue.issue.set_multiple_status";
listview.page.add_menu_item(__("Set as Open"), function() {

View File

@ -14,5 +14,5 @@ def get_context(context):
context.parents = frappe.form_dict.parents
if not context.doc.has_permission("read"):
if not context.doc.has_website_permission("read"):
frappe.throw(_("Not Permitted"), frappe.PermissionError)

View File

@ -1 +1,2 @@
DocType: Account,Accounts,དངུལ་རྩིས།
DocType: Pricing Rule,Buying,ཉོ་བ།

1 DocType: Account Accounts དངུལ་རྩིས།
2 DocType: Pricing Rule Buying ཉོ་བ།

File diff suppressed because it is too large Load Diff

View File

@ -37,7 +37,7 @@ DocType: Department,Department,Département
DocType: Purchase Order,% Billed,Facturé%
apps/erpnext/erpnext/controllers/sales_and_purchase_return.py +44,Exchange Rate must be same as {0} {1} ({2}),Taux de change doit être le même que {0} {1} ({2})
DocType: Sales Invoice,Customer Name,Nom du client
DocType: Features Setup,"All export related fields like currency, conversion rate, export total, export grand total etc are available in Delivery Note, POS, Quotation, Sales Invoice, Sales Order etc.","Tous les champs liés à l'exportation comme monnaie , taux de conversion , l'exportation totale , l'exportation totale grandiose etc sont disponibles dans la note de livraison , POS , offre , facture de vente , Sales Order etc"
DocType: Features Setup,"All export related fields like currency, conversion rate, export total, export grand total etc are available in Delivery Note, POS, Quotation, Sales Invoice, Sales Order etc.","Tous les champs liés à l'exportation comme monnaie , taux de conversion , l'exportation totale , l'exportation totale grandiose etc sont disponibles dans Bon de livraison , Point de Vente , Devis, Factures, Bons de commandes etc"
DocType: Account,Heads (or groups) against which Accounting Entries are made and balances are maintained.,Chefs (ou groupes) contre lequel les entrées comptables sont faites et les soldes sont maintenus.
apps/erpnext/erpnext/accounts/doctype/gl_entry/gl_entry.py +154,Outstanding for {0} cannot be less than zero ({1}),Participation pour les employés {0} est déjà marqué
DocType: Manufacturing Settings,Default 10 mins,Par défaut 10 minutes
@ -337,7 +337,7 @@ apps/erpnext/erpnext/hr/report/monthly_attendance_sheet/monthly_attendance_sheet
DocType: Purchase Invoice,"Enter email id separated by commas, invoice will be mailed automatically on particular date","Entrez Identifiant courriels séparé par des virgules, la facture sera envoyée automatiquement à la date particulière"
DocType: Employee,Company Email,E-mail entreprise
DocType: Workflow State,Refresh,Rafraîchir
DocType: Features Setup,"All import related fields like currency, conversion rate, import total, import grand total etc are available in Purchase Receipt, Supplier Quotation, Purchase Invoice, Purchase Order etc.","Tous les champs importation connexes comme monnaie , taux de conversion , totale d'importation , importation grande etc totale sont disponibles en Achat réception , Fournisseur d'offre , facture d'achat , bon de commande , etc"
DocType: Features Setup,"All import related fields like currency, conversion rate, import total, import grand total etc are available in Purchase Receipt, Supplier Quotation, Purchase Invoice, Purchase Order etc.","Tous les champs importation connexes comme monnaie , taux de conversion , total d'importation , importation grande etc totale sont disponibles en Achat réception , Devis fournisseur , Facture d'achat , bon de commande , etc"
apps/erpnext/erpnext/stock/doctype/item/item.js +29,This Item is a Template and cannot be used in transactions. Item attributes will be copied over into the variants unless 'No Copy' is set,Cet article est un modèle et ne peut être utilisé dans les transactions. Attributs d'élément seront copiés dans les variantes moins 'No Copy »est réglé
apps/erpnext/erpnext/selling/report/customers_not_buying_since_long_time/customers_not_buying_since_long_time.py +69,Total Order Considered,Total de la commande Considéré
apps/erpnext/erpnext/config/hr.py +110,"Employee designation (e.g. CEO, Director etc.).",Vous devez enregistrer le formulaire avant de procéder
@ -392,7 +392,7 @@ apps/erpnext/erpnext/setup/page/setup_wizard/fixtures/operations.py +35,Tube bea
apps/erpnext/erpnext/manufacturing/doctype/workstation/workstation.py +79,Workstation is closed on the following dates as per Holiday List: {0},Workstation est fermé aux dates suivantes selon la liste de vacances: {0}
apps/erpnext/erpnext/selling/doctype/sales_order/sales_order.js +627,Make Maint. Schedule,Assurez- Maint . calendrier
DocType: Employee,Single,Unique
DocType: Issue,Attachment,Attachement
DocType: Issue,Attachment,Pièce jointe
apps/erpnext/erpnext/accounts/doctype/cost_center/cost_center.py +29,Budget cannot be set for Group Cost Center,Budget ne peut pas être réglé pour le centre de coûts du Groupe
DocType: Account,Cost of Goods Sold,Montant payé + Write Off montant ne peut être supérieur à Total
DocType: Purchase Invoice,Yearly,Annuel
@ -1901,7 +1901,7 @@ apps/erpnext/erpnext/stock/get_item_details.py +103,No Item with Barcode {0},Bon
apps/erpnext/erpnext/stock/doctype/packing_slip/packing_slip.js +51,Case No. cannot be 0,Cas n ° ne peut pas être 0
DocType: Features Setup,If you have Sales Team and Sale Partners (Channel Partners) they can be tagged and maintain their contribution in the sales activity,"Si vous avez équipe de vente et Partenaires Vente (Channel Partners), ils peuvent être marqués et maintenir leur contribution à l&#39;activité commerciale"
DocType: Item,Show a slideshow at the top of the page,Afficher un diaporama en haut de la page
DocType: Item,"Allow in Sales Order of type ""Service""",Permettre à la commande client de type &quot;service&quot;
DocType: Item,"Allow in Sales Order of type ""Service""","Autoriser dans les bon de commandes de type ""Service"""
apps/erpnext/erpnext/setup/doctype/company/company.py +77,Stores,Magasins
DocType: Time Log,Projects Manager,Gestionnaire de projets
DocType: Serial No,Delivery Time,L'heure de la livraison
@ -2427,7 +2427,7 @@ apps/erpnext/erpnext/shopping_cart/utils.py +43,Orders,Commandes
DocType: Leave Control Panel,Employee Type,Type de contrat
DocType: Employee Leave Approver,Leave Approver,Laisser approbateur
apps/erpnext/erpnext/setup/page/setup_wizard/fixtures/operations.py +69,Swaging,Emboutissage
DocType: Expense Claim,"A user with ""Expense Approver"" role","Un utilisateur avec le rôle ""frais approbateur"""
DocType: Expense Claim,"A user with ""Expense Approver"" role","Un utilisateur avec le rôle ""Autorise les dépenses"""
,Issued Items Against Production Order,Articles émis contre un ordre de fabrication
DocType: Pricing Rule,Purchase Manager,Directeur des achats
DocType: Payment Tool,Payment Tool,Paiement Outil
@ -3917,7 +3917,7 @@ apps/erpnext/erpnext/setup/page/setup_wizard/setup_wizard.js +528,Purchaser,Ache
apps/erpnext/erpnext/hr/doctype/salary_structure/salary_structure.py +81,Net pay cannot be negative,Landed Cost correctement mis à jour
apps/erpnext/erpnext/accounts/doctype/payment_tool/payment_tool.py +70,Please enter the Against Vouchers manually,Se il vous plaît entrer le contre Chèques manuellement
DocType: SMS Settings,Static Parameters,Paramètres statiques
DocType: Purchase Order,Advance Paid,Payé Advance
DocType: Purchase Order,Advance Paid,Acompte payée
DocType: Item,Item Tax,Taxe sur l'Article
DocType: Expense Claim,Employees Email Id,Identifiants email des employés
apps/erpnext/erpnext/accounts/doctype/account/chart_of_accounts/verified/standard_chart_of_accounts.py +159,Current Liabilities,Le solde doit être

1 DocType: Employee Salary Mode Mode de rémunération
37 DocType: Purchase Order % Billed Facturé%
38 apps/erpnext/erpnext/controllers/sales_and_purchase_return.py +44 Exchange Rate must be same as {0} {1} ({2}) Taux de change doit être le même que {0} {1} ({2})
39 DocType: Sales Invoice Customer Name Nom du client
40 DocType: Features Setup All export related fields like currency, conversion rate, export total, export grand total etc are available in Delivery Note, POS, Quotation, Sales Invoice, Sales Order etc. Tous les champs liés à l'exportation comme monnaie , taux de conversion , l'exportation totale , l'exportation totale grandiose etc sont disponibles dans la note de livraison , POS , offre , facture de vente , Sales Order etc Tous les champs liés à l'exportation comme monnaie , taux de conversion , l'exportation totale , l'exportation totale grandiose etc sont disponibles dans Bon de livraison , Point de Vente , Devis, Factures, Bons de commandes etc
41 DocType: Account Heads (or groups) against which Accounting Entries are made and balances are maintained. Chefs (ou groupes) contre lequel les entrées comptables sont faites et les soldes sont maintenus.
42 apps/erpnext/erpnext/accounts/doctype/gl_entry/gl_entry.py +154 Outstanding for {0} cannot be less than zero ({1}) Participation pour les employés {0} est déjà marqué
43 DocType: Manufacturing Settings Default 10 mins Par défaut 10 minutes
337 DocType: Features Setup All import related fields like currency, conversion rate, import total, import grand total etc are available in Purchase Receipt, Supplier Quotation, Purchase Invoice, Purchase Order etc. Tous les champs importation connexes comme monnaie , taux de conversion , totale d'importation , importation grande etc totale sont disponibles en Achat réception , Fournisseur d'offre , facture d'achat , bon de commande , etc Tous les champs importation connexes comme monnaie , taux de conversion , total d'importation , importation grande etc totale sont disponibles en Achat réception , Devis fournisseur , Facture d'achat , bon de commande , etc
338 apps/erpnext/erpnext/stock/doctype/item/item.js +29 This Item is a Template and cannot be used in transactions. Item attributes will be copied over into the variants unless 'No Copy' is set Cet article est un modèle et ne peut être utilisé dans les transactions. Attributs d'élément seront copiés dans les variantes moins 'No Copy »est réglé
339 apps/erpnext/erpnext/selling/report/customers_not_buying_since_long_time/customers_not_buying_since_long_time.py +69 Total Order Considered Total de la commande Considéré
340 apps/erpnext/erpnext/config/hr.py +110 Employee designation (e.g. CEO, Director etc.). Vous devez enregistrer le formulaire avant de procéder
341 apps/erpnext/erpnext/controllers/recurring_document.py +200 Please enter 'Repeat on Day of Month' field value 1 devise = [ ? ] Fraction
342 DocType: Sales Invoice Rate at which Customer Currency is converted to customer's base currency Vitesse à laquelle la devise du client est converti en devise de base du client
343 DocType: Features Setup Available in BOM, Delivery Note, Purchase Invoice, Production Order, Purchase Order, Purchase Receipt, Sales Invoice, Sales Order, Stock Entry, Timesheet Disponible en nomenclature , bon de livraison , facture d'achat , ordre de production, bon de commande , bon de réception , la facture de vente , Sales Order , Stock entrée , des feuilles de temps
392 DocType: Account Cost of Goods Sold Montant payé + Write Off montant ne peut être supérieur à Total
393 DocType: Purchase Invoice Yearly Annuel
394 apps/erpnext/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.py +223 Please enter Cost Center S'il vous plaît entrer Centre de coûts
395 DocType: Sales Invoice Item Sales Order Commande
396 apps/erpnext/erpnext/accounts/report/gross_profit/gross_profit.py +63 Avg. Selling Rate Moy. Taux de vente
397 DocType: Purchase Order Start date of current order's period Date de la période de l'ordre courant de démarrage
398 apps/erpnext/erpnext/utilities/transaction_base.py +128 Quantity cannot be a fraction in row {0} Quantité ne peut pas être une fraction de la rangée
1901 DocType: Employee Education Post Graduate Message d&#39;études supérieures
1902 DocType: Backup Manager Note: Backups and files are not deleted from Dropbox, you will have to delete them manually. Remarque: Les sauvegardes et les fichiers ne sont pas effacés de Dropbox, vous devrez supprimer manuellement.
1903 DocType: Maintenance Schedule Detail Maintenance Schedule Detail Détail calendrier d&#39;entretien
1904 DocType: Quality Inspection Reading Reading 9 Lecture 9
1905 DocType: Supplier Is Frozen Est Gelé
1906 DocType: Buying Settings Buying Settings Réglages d&#39;achat
1907 apps/erpnext/erpnext/setup/page/setup_wizard/fixtures/operations.py +121 Mass finishing La finition de masse
2427 DocType: Production Plan Sales Order SO Date SO Date
2428 apps/erpnext/erpnext/stock/doctype/manage_variants/manage_variants.py +77 Attribute value {0} does not exist in Item Attribute Master. Valeur de l&#39;attribut {0} n&#39;&#39;existe pas dans l&#39;article Attribut Maître.
2429 DocType: Sales Invoice Rate at which Price list currency is converted to customer's base currency Taux auquel la monnaie Liste de prix est converti en devise de base du client
2430 DocType: Purchase Invoice Item Net Amount (Company Currency) Montant net (Société devise)
2431 DocType: BOM Operation Hour Rate Taux horraire
2432 DocType: Stock Settings Item Naming By Point de noms en
2433 apps/erpnext/erpnext/selling/doctype/sales_order/sales_order.js +637 From Quotation De offre
3917
3918
3919
3920
3921
3922
3923

View File

@ -772,7 +772,7 @@ apps/erpnext/erpnext/setup/page/setup_wizard/fixtures/operations.py +15,Permanen
DocType: Sales Order Item,Projected Qty,Qtde. Projetada
DocType: Sales Invoice,Payment Due Date,Data de Vencimento
DocType: Newsletter,Newsletter Manager,Boletim Gerente
apps/erpnext/erpnext/stock/report/stock_ledger/stock_ledger.py +95,'Opening','Aberto'
apps/erpnext/erpnext/stock/report/stock_ledger/stock_ledger.py +95,'Opening','Abrindo'
DocType: Notification Control,Delivery Note Message,Mensagem da Guia de Remessa
DocType: Expense Claim,Expenses,Despesas
,Purchase Receipt Trends,Compra Trends Recibo
@ -1370,7 +1370,7 @@ DocType: HR Settings,Stop Birthday Reminders,Parar Aniversário Lembretes
DocType: SMS Center,Receiver List,Lista de recebedores
DocType: Payment Tool Detail,Payment Amount,Valor do Pagamento
apps/erpnext/erpnext/stock/report/supplier_wise_sales_analytics/supplier_wise_sales_analytics.py +46,Consumed Amount,Quantidade consumida
sites/assets/js/erpnext.min.js +49,{0} View,{0} Vista
sites/assets/js/erpnext.min.js +49,{0} View,{0} Visão
DocType: Salary Structure Deduction,Salary Structure Deduction,Dedução da Estrutura Salarial
apps/erpnext/erpnext/setup/page/setup_wizard/fixtures/operations.py +157,Selective laser sintering,Seletiva sinterização a laser
apps/erpnext/erpnext/stock/doctype/item/item.py +153,Unit of Measure {0} has been entered more than once in Conversion Factor Table,Unidade de Medida {0} foi inserida mais de uma vez na Tabela de Conversão de Fator
@ -2152,7 +2152,7 @@ DocType: Landed Cost Voucher,Purchase Receipt Items,Itens do Recibo de Compra
apps/erpnext/erpnext/config/learn.py +21,Customizing Forms,Formas de personalização
apps/erpnext/erpnext/setup/page/setup_wizard/fixtures/operations.py +61,Cutting,Corte
apps/erpnext/erpnext/setup/page/setup_wizard/fixtures/operations.py +68,Flattening,Achatamento
DocType: Account,Income Account,Conta de Renda
DocType: Account,Income Account,Conta de Receitas
apps/erpnext/erpnext/setup/page/setup_wizard/fixtures/operations.py +21,Molding,Modelagem
DocType: Stock Reconciliation Item,Current Qty,Qtde atual
DocType: BOM Item,"See ""Rate Of Materials Based On"" in Costing Section",Consulte &quot;taxa de materiais baseados em&quot; no Custeio Seção
@ -3548,7 +3548,7 @@ DocType: Time Log,For Manufacturing,Para Manufacturing
apps/erpnext/erpnext/accounts/report/general_ledger/general_ledger.py +124,Totals,Totais
DocType: BOM,Manufacturing,Fabricação
,Ordered Items To Be Delivered,Itens encomendados a serem entregues
DocType: Account,Income,renda
DocType: Account,Income,Receitas
,Setup Wizard,Assistente de Configuração
DocType: Industry Type,Industry Type,Tipo de indústria
apps/erpnext/erpnext/templates/includes/cart.js +265,Something went wrong!,Algo deu errado!

1 DocType: Employee Salary Mode Modo de salário
772 DocType: Employee Ms Sra.
773 apps/erpnext/erpnext/config/accounts.py +143 Currency exchange rate master. Taxa de Câmbio Mestre
774 apps/erpnext/erpnext/manufacturing/doctype/production_order/production_order.py +248 Unable to find Time Slot in the next {0} days for Operation {1} Incapaz de encontrar entalhe Tempo nos próximos {0} dias para a Operação {1}
775 DocType: Production Order Plan material for sub-assemblies Material de Plano de sub-conjuntos
776 apps/erpnext/erpnext/manufacturing/doctype/bom/bom.py +427 BOM {0} must be active BOM {0} deve ser ativo
777 apps/erpnext/erpnext/stock/doctype/serial_no/serial_no.js +22 Set Status as Available Definir status como Disponível
778 apps/erpnext/erpnext/selling/report/sales_person_wise_transaction_summary/sales_person_wise_transaction_summary.py +26 Please select the document type first Por favor, selecione o tipo de documento primeiro
1370 apps/erpnext/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.py +56 None of the items have any change in quantity or value. Nenhum dos itens tiver qualquer mudança na quantidade ou valor.
1371 DocType: Warranty Claim Warranty Claim Reclamação de Garantia
1372 Lead Details Detalhes do Prospecto
1373 DocType: Authorization Rule Approving User Usuário Aprovador
1374 apps/erpnext/erpnext/setup/page/setup_wizard/fixtures/operations.py +36 Forging Forjar
1375 apps/erpnext/erpnext/setup/page/setup_wizard/fixtures/operations.py +125 Plating Galvanização
1376 DocType: Purchase Invoice End date of current invoice's period Data final do período de fatura atual
2152 apps/erpnext/erpnext/projects/doctype/time_log/time_log_list.js +13 Please select Time Logs. Por favor seleccione Tempo Logs.
2153 apps/erpnext/erpnext/accounts/doctype/pos_profile/pos_profile.py +43 {0} does not belong to Company {1} {0} não pertence à empresa {1}
2154 DocType: Account Round Off Termine
2155 Requested Qty solicitado Qtde
2156 DocType: BOM Item Scrap % Sucata %
2157 apps/erpnext/erpnext/stock/doctype/landed_cost_voucher/landed_cost_voucher.js +38 Charges will be distributed proportionately based on item qty or amount, as per your selection Encargos serão distribuídos proporcionalmente com base no qty item ou quantidade, como por sua seleção
2158 DocType: Maintenance Visit Purposes Fins
3548 apps/erpnext/erpnext/accounts/doctype/sales_invoice/sales_invoice.py +324 Item Code required at Row No {0} Código do item exigido no Row Não {0}
3549 DocType: Sales Partner Partner Type Tipo de parceiro
3550 DocType: Purchase Taxes and Charges Actual Atual
3551 DocType: Purchase Order % of materials received against this Purchase Order % do material recebido contra esta Ordem de Compra
3552 DocType: Authorization Rule Customerwise Discount Desconto referente ao Cliente
3553 DocType: Purchase Invoice Against Expense Account Contra a Conta de Despesas
3554 DocType: Production Order Production Order Ordem de Produção

View File

@ -330,7 +330,7 @@ DocType: Backup Manager,Allow Dropbox Access,Разрешить Dropbox Access
apps/erpnext/erpnext/config/learn.py +72,Setting up Taxes,Настройка Налоги
DocType: Communication,Support Manager,Поддержка менеджер
apps/erpnext/erpnext/accounts/utils.py +182,Payment Entry has been modified after you pulled it. Please pull it again.,"Оплата запись была изменена после того, как вытащил его. Пожалуйста, вытащить его снова."
apps/erpnext/erpnext/stock/doctype/item/item.py +195,{0} entered twice in Item Tax,{0} вводится дважды в пункт налоге
apps/erpnext/erpnext/stock/doctype/item/item.py +195,{0} entered twice in Item Tax,{0} вводится дважды в пункт налог
DocType: Workstation,Rent Cost,Стоимость аренды
DocType: Manage Variants Item,Variant Attributes,Вариант Атрибуты
apps/erpnext/erpnext/hr/report/monthly_attendance_sheet/monthly_attendance_sheet.py +73,Please select month and year,"Пожалуйста, выберите месяц и год"
@ -346,7 +346,7 @@ DocType: Sales Invoice,Rate at which Customer Currency is converted to customer'
DocType: Features Setup,"Available in BOM, Delivery Note, Purchase Invoice, Production Order, Purchase Order, Purchase Receipt, Sales Invoice, Sales Order, Stock Entry, Timesheet","Доступный в спецификации, накладной, счете-фактуре, производственного заказа, заказа на поставку, покупка получение, счет-фактура, заказ клиента, фондовой въезда, расписания"
DocType: Item Tax,Tax Rate,Размер налога
apps/erpnext/erpnext/buying/doctype/purchase_order/purchase_order.js +504,Select Item,Выбрать пункт
apps/erpnext/erpnext/selling/doctype/sales_order/sales_order.py +208,{0} {1} status is Stopped,{0} {1} положение остановлен
apps/erpnext/erpnext/selling/doctype/sales_order/sales_order.py +208,{0} {1} status is Stopped,{0} {1} статус остановлен
apps/erpnext/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.py +143,"Item: {0} managed batch-wise, can not be reconciled using \
Stock Reconciliation, instead use Stock Entry","Пункт: {0} удалось порционно, не могут быть согласованы с помощью \
со примирения, вместо этого использовать со запись"
@ -385,7 +385,7 @@ apps/erpnext/erpnext/accounts/doctype/pricing_rule/pricing_rule.js +57,"If multi
,Purchase Register,Покупка Становиться на учет
DocType: Landed Cost Item,Applicable Charges,Взимаемых платежах
DocType: Workstation,Consumable Cost,Расходные Стоимость
apps/erpnext/erpnext/hr/doctype/leave_application/leave_application.py +153,{0} ({1}) must have role 'Leave Approver',"{0} ({1}) должен иметь роль ""Утверждающего Убытки"""
apps/erpnext/erpnext/hr/doctype/leave_application/leave_application.py +153,{0} ({1}) must have role 'Leave Approver',"{0} ({1}) должен иметь роль ""Подтверждающего Отсутствие"""
apps/erpnext/erpnext/setup/page/setup_wizard/install_fixtures.py +39,Medical,Медицинский
apps/erpnext/erpnext/crm/doctype/opportunity/opportunity.js +124,Reason for losing,Причина потери
apps/erpnext/erpnext/setup/page/setup_wizard/fixtures/operations.py +35,Tube beading,Труба бисером
@ -461,7 +461,7 @@ sites/assets/js/erpnext.min.js +54,Please select Company,"Пожалуйста,
DocType: Stock Entry,Difference Account,Счет разницы
apps/erpnext/erpnext/projects/doctype/task/task.py +44,Cannot close task as its dependant task {0} is not closed.,"Невозможно закрыть задача, как ее зависит задача {0} не закрыт."
apps/erpnext/erpnext/manufacturing/doctype/production_planning_tool/production_planning_tool.py +298,Please enter Warehouse for which Material Request will be raised,"Пожалуйста, введите Склад для которых Материал Запрос будет поднят"
DocType: Production Order,Additional Operating Cost,Дополнительная Эксплуатационные расходы
DocType: Production Order,Additional Operating Cost,Дополнительные Эксплуатационные расходы
apps/erpnext/erpnext/setup/page/setup_wizard/fixtures/industry_type.py +19,Cosmetics,Косметика
DocType: DocField,Type,Тип
apps/erpnext/erpnext/stock/doctype/item/item.py +272,"To merge, following properties must be same for both items","Чтобы объединить, следующие свойства должны быть одинаковыми для обоих пунктов"
@ -490,8 +490,8 @@ DocType: Variant Attribute,Variant Attribute,Вариант Атрибут
DocType: Company,Delete Company Transactions,Удалить Сделки Компания
apps/erpnext/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py +84,Item {0} is not Purchase Item,Пункт {0} не Приобретите товар
apps/erpnext/erpnext/controllers/recurring_document.py +189,"{0} is an invalid email address in 'Notification \
Email Address'","{0} неправильный адрес электронной почты в ""\
Уведомление адресом электронной почты"""
Email Address'","{0} неправильный адрес электронной почты в ""
Уведомление \ адрес электронной почты"""
apps/erpnext/erpnext/buying/doctype/supplier/supplier.js +44,Total Billing This Year:,Всего счетов в этом году:
DocType: Purchase Receipt,Add / Edit Taxes and Charges,Добавить / Изменить Налоги и сборы
DocType: Purchase Invoice,Supplier Invoice No,Поставщик Счет Нет
@ -542,7 +542,7 @@ apps/erpnext/erpnext/accounts/page/financial_analytics/financial_analytics.js +5
apps/erpnext/erpnext/accounts/utils.py +186,Allocated amount can not be negative,Выделенные сумма не может быть отрицательным
apps/erpnext/erpnext/setup/page/setup_wizard/fixtures/operations.py +122,Tumbling,Акробатика
DocType: Purchase Order Item,Billed Amt,Счетов выдано кол-во
DocType: Warehouse,A logical Warehouse against which stock entries are made.,"Логично Склад, на котором фондовые записи сделаны."
DocType: Warehouse,A logical Warehouse against which stock entries are made.,"Логика Склада,по которому сделаны складские записи"
apps/erpnext/erpnext/accounts/doctype/journal_entry/journal_entry.py +110,Reference No & Reference Date is required for {0},Ссылка № & Ссылка Дата необходим для {0}
DocType: Event,Wednesday,Среда
DocType: Sales Invoice,Customer's Vendor,Производитель Клиентам
@ -593,7 +593,7 @@ apps/erpnext/erpnext/config/buying.py +28,Purchase Orders given to Suppliers.,"
apps/erpnext/erpnext/setup/page/setup_wizard/fixtures/industry_type.py +42,Publishing,Публикация
DocType: Activity Cost,Projects User,Проекты Пользователь
apps/erpnext/erpnext/stock/report/itemwise_recommended_reorder_level/itemwise_recommended_reorder_level.py +41,Consumed,Потребляемая
apps/erpnext/erpnext/accounts/doctype/payment_reconciliation/payment_reconciliation.py +187,{0}: {1} not found in Invoice Details table,{0} {1} не найден в счете-фактуре таблице
apps/erpnext/erpnext/accounts/doctype/payment_reconciliation/payment_reconciliation.py +187,{0}: {1} not found in Invoice Details table,{0} {1} не найден в таблице счета
DocType: Company,Round Off Cost Center,Округление Стоимость центр
apps/erpnext/erpnext/selling/doctype/sales_order/sales_order.py +189,Maintenance Visit {0} must be cancelled before cancelling this Sales Order,Техническое обслуживание Посетить {0} должно быть отменено до отмены этого заказ клиента
DocType: Material Request,Material Transfer,О передаче материала
@ -737,7 +737,7 @@ DocType: Process Payroll,Send Email,Отправить e-mail
apps/erpnext/erpnext/buying/doctype/supplier/supplier.py +85,No Permission,Нет разрешения
DocType: Company,Default Bank Account,По умолчанию Банковский счет
apps/erpnext/erpnext/accounts/report/general_ledger/general_ledger.py +43,"To filter based on Party, select Party Type first","Чтобы отфильтровать на основе партии, выберите партия первого типа"
apps/erpnext/erpnext/controllers/sales_and_purchase_return.py +49,'Update Stock' can not be checked because items are not delivered via {0},"&quot;Обновление со&quot; не могут быть проверены, так как элементы не поставляется через {0}"
apps/erpnext/erpnext/controllers/sales_and_purchase_return.py +49,'Update Stock' can not be checked because items are not delivered via {0},"""Обновления Склада"" не могут быть проверены, так как позиция не поставляется через {0}"
apps/erpnext/erpnext/setup/page/setup_wizard/setup_wizard.js +626,Nos,кол-во
DocType: Item,Items with higher weightage will be shown higher,"Элементы с более высокой weightage будет показано выше,"
DocType: Bank Reconciliation Detail,Bank Reconciliation Detail,Банковская сверка подробно
@ -759,7 +759,7 @@ DocType: Email Digest,Email Digest Settings,Email Дайджест Настро
apps/erpnext/erpnext/config/support.py +13,Support queries from customers.,Поддержка запросов от клиентов.
DocType: Bin,Moving Average Rate,Moving Average Rate
DocType: Production Planning Tool,Select Items,Выберите товары
apps/erpnext/erpnext/accounts/doctype/journal_entry/journal_entry.py +292,{0} against Bill {1} dated {2},{0} против Счета {1} от {2}
apps/erpnext/erpnext/accounts/doctype/journal_entry/journal_entry.py +292,{0} against Bill {1} dated {2},{0} по Счету {1} от {2}
DocType: Comment,Reference Name,Ссылка Имя
DocType: Maintenance Visit,Completion Status,Статус завершения
DocType: Production Order,Target Warehouse,Целевая Склад
@ -1372,7 +1372,7 @@ DocType: HR Settings,Stop Birthday Reminders,Стоп День рождения
DocType: SMS Center,Receiver List,Приемник Список
DocType: Payment Tool Detail,Payment Amount,Сумма платежа
apps/erpnext/erpnext/stock/report/supplier_wise_sales_analytics/supplier_wise_sales_analytics.py +46,Consumed Amount,Израсходованное количество
sites/assets/js/erpnext.min.js +49,{0} View,{0} Посмотреть
sites/assets/js/erpnext.min.js +49,{0} View,{0} Просмотр
DocType: Salary Structure Deduction,Salary Structure Deduction,Зарплата Структура Вычет
apps/erpnext/erpnext/setup/page/setup_wizard/fixtures/operations.py +157,Selective laser sintering,Селективный лазерного спекания
apps/erpnext/erpnext/stock/doctype/item/item.py +153,Unit of Measure {0} has been entered more than once in Conversion Factor Table,Единица измерения {0} был введен более чем один раз в таблицу преобразования Factor
@ -1515,7 +1515,7 @@ apps/erpnext/erpnext/shopping_cart/utils.py +47,Addresses,Адреса
DocType: Communication,Received,Получено
apps/erpnext/erpnext/accounts/doctype/journal_entry/journal_entry.py +155,Against Journal Entry {0} does not have any unmatched {1} entry,Против Запись в журнале {0} не имеет никакого непревзойденную {1} запись
apps/erpnext/erpnext/stock/doctype/serial_no/serial_no.py +216,Duplicate Serial No entered for Item {0},Дубликат Серийный номер вводится для Пункт {0}
DocType: Shipping Rule Condition,A condition for a Shipping Rule,Состояние для правила судоходства
DocType: Shipping Rule Condition,A condition for a Shipping Rule,Условия для правил перевозки
apps/erpnext/erpnext/manufacturing/doctype/production_order/production_order.py +326,Item is not allowed to have Production Order.,Деталь не разрешается иметь производственного заказа.
apps/erpnext/erpnext/accounts/page/accounts_browser/accounts_browser.js +205,"Name of new Account. Note: Please don't create accounts for Customers and Suppliers, they are created automatically from the Customer and Supplier master","Имя нового счета. Примечание: Пожалуйста, не создавать учетные записи для клиентов и поставщиков, они создаются автоматически от Заказчика и поставщика оригиналов"
DocType: DocField,Attach Image,Прикрепить изображение
@ -1989,7 +1989,7 @@ apps/erpnext/erpnext/manufacturing/doctype/bom/bom.js +92,You can not change rat
DocType: Employee,Previous Work Experience,Предыдущий опыт работы
DocType: Stock Entry,For Quantity,Для Количество
apps/erpnext/erpnext/manufacturing/doctype/production_planning_tool/production_planning_tool.py +153,Please enter Planned Qty for Item {0} at row {1},"Пожалуйста, введите Запланированное Количество по пункту {0} в строке {1}"
apps/erpnext/erpnext/accounts/doctype/journal_entry/journal_entry.py +217,{0} {1} is not submitted,{0} {1} не отправлен
apps/erpnext/erpnext/accounts/doctype/journal_entry/journal_entry.py +217,{0} {1} is not submitted,{0} {1} не проведен
apps/erpnext/erpnext/config/stock.py +13,Requests for items.,Запросы на предметы.
DocType: Production Planning Tool,Separate production order will be created for each finished good item.,Отдельный производственный заказ будет создан для каждого готового хорошего пункта.
DocType: Email Digest,New Communications,Новые Коммуникации
@ -2034,7 +2034,7 @@ DocType: Sales Partner,A third party distributor / dealer / commission agent / a
DocType: Customer Group,Has Child Node,Имеет дочерний узел
apps/erpnext/erpnext/accounts/doctype/journal_entry/journal_entry.py +296,{0} against Purchase Order {1},{0} против Заказа {1}
DocType: SMS Settings,"Enter static url parameters here (Eg. sender=ERPNext, username=ERPNext, password=1234 etc.)","Введите статические параметры адрес здесь (Например отправитель = ERPNext, имя пользователя = ERPNext, пароль = 1234 и т.д.)"
apps/erpnext/erpnext/accounts/utils.py +39,{0} {1} not in any active Fiscal Year. For more details check {2}.,"{0} {1}, не в какой-либо активной финансовый год. Для более подробной информации проверить {2}."
apps/erpnext/erpnext/accounts/utils.py +39,{0} {1} not in any active Fiscal Year. For more details check {2}.,"{0} {1}, ни в каком-либо активном финансовом году. Для более подробной информации проверить {2}."
apps/erpnext/erpnext/setup/page/setup_wizard/default_website.py +26,This is an example website auto-generated from ERPNext,Это пример сайт автоматически сгенерированный из ERPNext
apps/erpnext/erpnext/accounts/report/accounts_payable/accounts_payable.js +37,Ageing Range 1,Старение Диапазон 1
apps/erpnext/erpnext/setup/page/setup_wizard/fixtures/operations.py +109,Photochemical machining,Фотохимические обработки
@ -2505,7 +2505,7 @@ DocType: Payment Tool,Against Vouchers,На ваучеры
apps/erpnext/erpnext/accounts/page/accounts_browser/accounts_browser.js +23,Quick Help,Быстрая помощь
apps/erpnext/erpnext/stock/doctype/stock_entry/stock_entry.py +169,Source and target warehouse cannot be same for row {0},Источник и цель склад не может быть одинаковым для ряда {0}
DocType: Features Setup,Sales Extras,Продажи Дополнительно
apps/erpnext/erpnext/accounts/utils.py +311,{0} budget for Account {1} against Cost Center {2} will exceed by {3},{0} бюджет на счет {1} против МВЗ {2} будет превышать {3}
apps/erpnext/erpnext/accounts/utils.py +311,{0} budget for Account {1} against Cost Center {2} will exceed by {3},{0} бюджет на счет {1} к МВЗ {2} будет превышать {3}
apps/erpnext/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.py +236,"Difference Account must be a Asset/Liability type account, since this Stock Reconciliation is an Opening Entry","Разница аккаунт должен быть тип счета активов / пассивов, так как это со Примирение запись Открытие"
apps/erpnext/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py +123,Purchase Order number required for Item {0},Число Заказ требуется для Пункт {0}
DocType: Leave Allocation,Carry Forwarded Leaves,Carry направляются листья
@ -2796,7 +2796,7 @@ DocType: Notification Control,Custom Message,Текст сообщения
apps/erpnext/erpnext/setup/page/setup_wizard/fixtures/industry_type.py +32,Investment Banking,Инвестиционно-банковская деятельность
apps/erpnext/erpnext/setup/page/setup_wizard/setup_wizard.js +261,"Select your Country, Time Zone and Currency","Выберите страну, часовой пояс и валюта"
apps/erpnext/erpnext/accounts/doctype/sales_invoice/sales_invoice.py +314,Cash or Bank Account is mandatory for making payment entry,Наличными или банковский счет является обязательным для внесения записи платежей
apps/erpnext/erpnext/selling/doctype/sales_order/sales_order.py +214,{0} {1} status is Unstopped,{0} {1} статус отверзутся
apps/erpnext/erpnext/selling/doctype/sales_order/sales_order.py +214,{0} {1} status is Unstopped,{0} {1} статус активирован
DocType: Purchase Invoice,Price List Exchange Rate,Прайс-лист валютный курс
apps/erpnext/erpnext/setup/page/setup_wizard/fixtures/operations.py +90,Pickling,Маринование
apps/erpnext/erpnext/setup/page/setup_wizard/fixtures/operations.py +17,Sand casting,Литье в песчаные
@ -3063,7 +3063,7 @@ DocType: Sales Invoice,Posting Time,Средняя Время
DocType: Sales Order,% Amount Billed,% Сумма счета
apps/erpnext/erpnext/accounts/doctype/account/chart_of_accounts/verified/standard_chart_of_accounts.py +129,Telephone Expenses,Телефон Расходы
DocType: Sales Partner,Logo,Логотип
apps/erpnext/erpnext/stock/doctype/serial_no/serial_no.py +212,{0} Serial Numbers required for Item {0}. Only {0} provided.,"{0} Серийные номера, необходимые для Пункт {0}. Только {0} предусмотрено."
apps/erpnext/erpnext/stock/doctype/serial_no/serial_no.py +212,{0} Serial Numbers required for Item {0}. Only {0} provided.,"{0} Серийные номера, обязательные для позиции {0}. Только {0} предусмотрено."
DocType: Naming Series,Check this if you want to force the user to select a series before saving. There will be no default if you check this.,"Проверьте это, если вы хотите, чтобы заставить пользователя выбрать серию перед сохранением. Там не будет по умолчанию, если вы проверить это."
apps/erpnext/erpnext/stock/get_item_details.py +107,No Item with Serial No {0},Нет товара с серийным № {0}
apps/erpnext/erpnext/accounts/doctype/account/chart_of_accounts/verified/standard_chart_of_accounts.py +68,Direct Expenses,Прямые расходы
@ -3122,7 +3122,7 @@ apps/erpnext/erpnext/config/selling.py +18,Quotes to Leads or Customers.,Кот
DocType: Stock Settings,Role Allowed to edit frozen stock,Роль разрешено редактировать Замороженный исходный
,Territory Target Variance Item Group-Wise,Территория Целевая Разница Пункт Группа Мудрого
apps/erpnext/erpnext/setup/page/setup_wizard/install_fixtures.py +101,All Customer Groups,Все Группы клиентов
apps/erpnext/erpnext/controllers/accounts_controller.py +399,{0} is mandatory. Maybe Currency Exchange record is not created for {1} to {2}.,"{0} является обязательным. Может быть, Обмен валюты запись не создана для {1} по {2}."
apps/erpnext/erpnext/controllers/accounts_controller.py +399,{0} is mandatory. Maybe Currency Exchange record is not created for {1} to {2}.,"{0} является обязательным. Может быть, запись Обмен валюты не создана для {1} по {2}."
apps/erpnext/erpnext/accounts/doctype/account/account.py +37,Account {0}: Parent account {1} does not exist,Счет {0}: Родитель счета {1} не существует
DocType: Purchase Invoice Item,Price List Rate (Company Currency),Прайс-лист Тариф (Компания Валюта)
apps/erpnext/erpnext/buying/doctype/purchase_common/purchase_common.py +83,{0} {1} status is 'Stopped',"{0} {1} статус ""Остановлен"""
@ -3147,7 +3147,7 @@ DocType: Lead,Add to calendar on this date,Добавить в календар
apps/erpnext/erpnext/config/selling.py +132,Rules for adding shipping costs.,Правила для добавления стоимости доставки.
apps/erpnext/erpnext/support/doctype/warranty_claim/warranty_claim.py +20,Customer is required,Требуется клиентов
DocType: Letter Head,Letter Head,Заголовок письма
apps/erpnext/erpnext/controllers/sales_and_purchase_return.py +21,{0} is mandatory for Return,{0} является обязательным для возвращения
apps/erpnext/erpnext/controllers/sales_and_purchase_return.py +21,{0} is mandatory for Return,{0} является обязательным для возврата
apps/erpnext/erpnext/buying/doctype/purchase_order/purchase_order_list.js +12,To Receive,Получить
apps/erpnext/erpnext/setup/page/setup_wizard/fixtures/operations.py +32,Shrink fitting,Термоусадочная Место
apps/erpnext/erpnext/setup/page/setup_wizard/setup_wizard.js +522,user@example.com,user@example.com
@ -3232,7 +3232,7 @@ apps/erpnext/erpnext/setup/page/setup_wizard/install_fixtures.py +44,Casual Leav
DocType: Batch,Batch ID,ID партии
apps/erpnext/erpnext/accounts/doctype/journal_entry/journal_entry.py +300,Note: {0},Примечание: {0}
,Delivery Note Trends,Доставка Примечание тенденции
apps/erpnext/erpnext/buying/doctype/purchase_common/purchase_common.py +72,{0} must be a Purchased or Sub-Contracted Item in row {1},{0} должен быть куплены или субподрядчиком Пункт в строке {1}
apps/erpnext/erpnext/buying/doctype/purchase_common/purchase_common.py +72,{0} must be a Purchased or Sub-Contracted Item in row {1},{0} позиция должна быть куплена или получена на основе субподряда в строке {1}
apps/erpnext/erpnext/accounts/general_ledger.py +92,Account: {0} can only be updated via Stock Transactions,Счет: {0} можно обновить только с помощью биржевых операций
DocType: GL Entry,Party,Сторона
DocType: Sales Order,Delivery Date,Дата поставки
@ -3530,7 +3530,7 @@ apps/erpnext/erpnext/projects/doctype/project/project_list.js +6,{0}% Complete,{
DocType: Employee,Educational Qualification,Образовательный ценз
DocType: Workstation,Operating Costs,Операционные расходы
DocType: Employee Leave Approver,Employee Leave Approver,Сотрудник Оставить утверждающий
apps/erpnext/erpnext/crm/doctype/newsletter/newsletter.py +167,{0} has been successfully added to our Newsletter list.,{0} был успешно добавлен в список наших новости.
apps/erpnext/erpnext/crm/doctype/newsletter/newsletter.py +167,{0} has been successfully added to our Newsletter list.,{0} был успешно добавлен в список наших новостей.
apps/erpnext/erpnext/stock/doctype/item/item.py +235,Row {0}: An Reorder entry already exists for this warehouse {1},Ряд {0}: запись Изменить порядок уже существует для этого склада {1}
apps/erpnext/erpnext/crm/doctype/opportunity/opportunity.py +66,"Cannot declare as lost, because Quotation has been made.","Не можете объявить как потерял, потому что цитаты было сделано."
apps/erpnext/erpnext/setup/page/setup_wizard/fixtures/operations.py +132,Electron beam machining,Электронно-лучевая обработка
@ -3822,7 +3822,7 @@ DocType: Customer,Credit Days Based On,Кредитные дней основа
apps/erpnext/erpnext/stock/doctype/stock_uom_replace_utility/stock_uom_replace_utility.py +57,Stock balances updated,Акции остатки обновляются
DocType: Selling Settings,Maintain Same Rate Throughout Sales Cycle,Поддержание же скоростью протяжении цикла продаж
DocType: Manufacturing Settings,Plan time logs outside Workstation Working Hours.,Планировать время журналы за пределами рабочего времени рабочих станций.
apps/erpnext/erpnext/buying/doctype/purchase_common/purchase_common.py +91,{0} {1} has already been submitted,{0} {1} уже отправлен
apps/erpnext/erpnext/buying/doctype/purchase_common/purchase_common.py +91,{0} {1} has already been submitted,{0} {1} уже проведен
,Items To Be Requested,"Предметы, будет предложено"
DocType: Purchase Order,Get Last Purchase Rate,Получить последнюю покупку Оценить
DocType: Company,Company Info,Информация о компании
@ -3849,7 +3849,7 @@ apps/erpnext/erpnext/config/accounts.py +18,Bills raised to Customers.,"Зако
DocType: DocField,Default,По умолчанию
apps/erpnext/erpnext/projects/report/project_wise_stock_tracking/project_wise_stock_tracking.py +26,Project Id,Проект Id
apps/erpnext/erpnext/accounts/doctype/journal_entry/journal_entry.py +431,Row No {0}: Amount cannot be greater than Pending Amount against Expense Claim {1}. Pending Amount is {2},"Ряд Нет {0}: Сумма не может быть больше, чем ожидании Сумма против Расход претензии {1}. В ожидании сумма {2}"
apps/erpnext/erpnext/crm/doctype/newsletter_list/newsletter_list.py +42,{0} subscribers added,{0} добавил абоненты
apps/erpnext/erpnext/crm/doctype/newsletter_list/newsletter_list.py +42,{0} subscribers added,{0} подписчики добавлены
DocType: Maintenance Schedule,Schedule,Расписание
DocType: Account,Parent Account,Родитель счета
DocType: Serial No,Available,имеется

1 DocType: Employee Salary Mode Режим Зарплата
330 apps/erpnext/erpnext/stock/doctype/item/item.py +195 {0} entered twice in Item Tax {0} вводится дважды в пункт налоге {0} вводится дважды в пункт налог
331 DocType: Workstation Rent Cost Стоимость аренды
332 DocType: Manage Variants Item Variant Attributes Вариант Атрибуты
333 apps/erpnext/erpnext/hr/report/monthly_attendance_sheet/monthly_attendance_sheet.py +73 Please select month and year Пожалуйста, выберите месяц и год
334 DocType: Purchase Invoice Enter email id separated by commas, invoice will be mailed automatically on particular date Введите электронный идентификатор разделенных запятыми, счет будет автоматически отправлен на определенную дату
335 DocType: Employee Company Email Email предприятия
336 DocType: Workflow State Refresh Обновить
346 apps/erpnext/erpnext/selling/doctype/sales_order/sales_order.py +208 {0} {1} status is Stopped {0} {1} положение остановлен {0} {1} статус остановлен
347 apps/erpnext/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.py +143 Item: {0} managed batch-wise, can not be reconciled using \ Stock Reconciliation, instead use Stock Entry Пункт: {0} удалось порционно, не могут быть согласованы с помощью \ со примирения, вместо этого использовать со запись
348 apps/erpnext/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py +242 Purchase Invoice {0} is already submitted Покупка Счет {0} уже подано
349 apps/erpnext/erpnext/accounts/doctype/account/account.js +54 Convert to non-Group Преобразовать в негрупповой
350 apps/erpnext/erpnext/stock/doctype/landed_cost_voucher/landed_cost_voucher.py +55 Purchase Receipt must be submitted Покупка Получение должны быть представлены
351 DocType: Stock UOM Replace Utility Current Stock UOM Наличие на складе Единица измерения
352 apps/erpnext/erpnext/config/stock.py +53 Batch (lot) of an Item. Партия элементов.
385 apps/erpnext/erpnext/crm/doctype/opportunity/opportunity.js +124 Reason for losing Причина потери
386 apps/erpnext/erpnext/setup/page/setup_wizard/fixtures/operations.py +35 Tube beading Труба бисером
387 apps/erpnext/erpnext/manufacturing/doctype/workstation/workstation.py +79 Workstation is closed on the following dates as per Holiday List: {0} Рабочая станция закрыта в следующие сроки согласно Список праздников: {0}
388 apps/erpnext/erpnext/selling/doctype/sales_order/sales_order.js +627 Make Maint. Schedule Сделать Maint. Расписание
389 DocType: Employee Single Единственный
390 DocType: Issue Attachment Привязанность
391 apps/erpnext/erpnext/accounts/doctype/cost_center/cost_center.py +29 Budget cannot be set for Group Cost Center Бюджет не может быть установлен для группы МВЗ
461 DocType: DocField Type Тип
462 apps/erpnext/erpnext/stock/doctype/item/item.py +272 To merge, following properties must be same for both items Чтобы объединить, следующие свойства должны быть одинаковыми для обоих пунктов
463 DocType: Backup Manager Email ids separated by commas. Email идентификаторы через запятую.
464 DocType: Communication Subject Тема
465 DocType: Shipping Rule Net Weight Вес нетто
466 DocType: Employee Emergency Phone В случае чрезвычайных ситуаций
467 DocType: Backup Manager Google Drive Access Allowed Разрешено Google Drive Доступ
490 DocType: Purchase Invoice Supplier Invoice No Поставщик Счет Нет
491 DocType: Territory For reference Для справки
492 apps/erpnext/erpnext/accounts/report/trial_balance/trial_balance.py +227 Closing (Cr) Закрытие (Cr)
493 DocType: Serial No Warranty Period (Days) Гарантийный срок (дней)
494 DocType: Installation Note Item Installation Note Item Установка Примечание Пункт
495 DocType: Job Applicant Thread HTML Тема HTML
496 DocType: Company Ignore Игнорировать
497 apps/erpnext/erpnext/setup/doctype/sms_settings/sms_settings.py +86 SMS sent to following numbers: {0} SMS отправлено следующих номеров: {0}
542 apps/erpnext/erpnext/stock/stock_ledger.py +337 Negative Stock Error ({6}) for Item {0} in Warehouse {1} on {2} {3} in {4} {5} Отрицательный Ошибка со ({6}) по пункту {0} в Склад {1} на {2} {3} в {4} {5}
543 DocType: Fiscal Year Company Fiscal Year Company Финансовый год компании
544 DocType: Packing Slip Item DN Detail DN Деталь
545 DocType: Time Log Billed Выдавать счета
546 DocType: Batch Batch Description Партия Описание
547 DocType: Delivery Note Time at which items were delivered from warehouse Момент, в который предметы были доставлены со склада
548 DocType: Sales Invoice Sales Taxes and Charges Продажи Налоги и сборы
593 DocType: Production Order Operation Actual Start Time Фактическое начало Время
594 DocType: BOM Operation Operation Time Время работы
595 sites/assets/js/list.min.js +5 More Далее
596 DocType: Communication Sales Manager Менеджер По Продажам
597 sites/assets/js/desk.min.js +641 Rename Переименовать
598 DocType: Purchase Invoice Write Off Amount Списание Количество
599 apps/erpnext/erpnext/setup/page/setup_wizard/fixtures/operations.py +51 Bending Изгиб
737 apps/erpnext/erpnext/setup/page/setup_wizard/fixtures/operations.py +74 Staking Разбивка
738 DocType: Item Re-Order Qty Re порядка Кол-во
739 DocType: Leave Block List Date Leave Block List Date Оставьте Блок-лист Дата
740 apps/erpnext/erpnext/crm/doctype/newsletter/newsletter.py +25 Scheduled to send to {0} Планируется отправить {0}
741 DocType: Pricing Rule Price or Discount Цена или Скидка
742 DocType: Sales Team Incentives Стимулы
743 DocType: SMS Log Requested Numbers Требуемые Номера
759 DocType: Serial No Incoming Rate Входящий Оценить
760 DocType: Packing Slip Gross Weight Вес брутто
761 apps/erpnext/erpnext/setup/page/setup_wizard/setup_wizard.js +410 The name of your company for which you are setting up this system. Название вашей компании, для которой вы настраиваете эту систему.
762 DocType: HR Settings Include holidays in Total no. of Working Days Включите праздники в общей сложности не. рабочих дней
763 DocType: Job Applicant Hold Удержание
764 DocType: Employee Date of Joining Дата вступления
765 DocType: Naming Series Update Series Обновление серий
1372 Lead Details Лид Подробности
1373 DocType: Authorization Rule Approving User Утверждении Пользователь
1374 apps/erpnext/erpnext/setup/page/setup_wizard/fixtures/operations.py +36 Forging Ковка
1375 apps/erpnext/erpnext/setup/page/setup_wizard/fixtures/operations.py +125 Plating Обшивка
1376 DocType: Purchase Invoice End date of current invoice's period Дата и время окончания периода текущего счета-фактуры в
1377 DocType: Pricing Rule Applicable For Применимо для
1378 apps/erpnext/erpnext/stock/doctype/item/item.py +342 Item Template cannot have stock or Open Sales/Purchase/Production Orders. Пункт Шаблон не может иметь акции или Открыть покупке / продаже / Производственные заказы.
1515 apps/erpnext/erpnext/hr/doctype/employee/employee.js +27 Make Salary Structure Сделать Зарплата Структура
1516 apps/erpnext/erpnext/setup/page/setup_wizard/fixtures/operations.py +53 Shearing Сдвиг
1517 DocType: Item Has Variants Имеет Варианты
1518 apps/erpnext/erpnext/projects/doctype/time_log_batch/time_log_batch.js +22 Click on 'Make Sales Invoice' button to create a new Sales Invoice. Нажмите на кнопку "Создать Расходная накладная», чтобы создать новый счет-фактуру.
1519 apps/erpnext/erpnext/controllers/recurring_document.py +166 Period From and Period To dates mandatory for recurring %s Период с и срок датам обязательных для повторяющихся% S
1520 DocType: Journal Entry Account Against Expense Claim На Расход претензии
1521 apps/erpnext/erpnext/setup/page/setup_wizard/fixtures/operations.py +165 Packaging and labeling Упаковка и маркировка
1989 apps/erpnext/erpnext/hr/doctype/leave_application/leave_application.js +43 This Leave Application is pending approval. Only the Leave Approver can update status. Это оставьте заявку ожидает одобрения. Только Оставить утверждающий можете обновить статус.
1990 DocType: Global Defaults Hide Currency Symbol Скрыть Символ Валюты
1991 apps/erpnext/erpnext/config/accounts.py +159 e.g. Bank, Cash, Credit Card например банк, наличные, кредитная карта
1992 DocType: Journal Entry Credit Note Кредит-нота
1993 apps/erpnext/erpnext/projects/doctype/time_log/time_log.py +207 Completed Qty cannot be more than {0} for operation {1} Завершен Кол-во не может быть больше {0} для работы {1}
1994 DocType: Features Setup Quality Качество
1995 DocType: Contact Us Settings Introduction Введение
2034 DocType: Employee Emergency Contact Экстренная связь
2035 DocType: Item Quality Parameters Параметры качества
2036 DocType: Target Detail Target Amount Целевая сумма
2037 DocType: Shopping Cart Settings Shopping Cart Settings Корзина Настройки
2038 DocType: Journal Entry Accounting Entries Бухгалтерские записи
2039 apps/erpnext/erpnext/setup/doctype/authorization_rule/authorization_rule.py +24 Duplicate Entry. Please check Authorization Rule {0} Копия записи. Пожалуйста, проверьте Авторизация Правило {0}
2040 apps/erpnext/erpnext/accounts/doctype/pos_profile/pos_profile.py +26 Global POS Profile {0} already created for company {1} Глобальный профиля POS {0} уже создана для компании {1}
2505 apps/erpnext/erpnext/setup/page/setup_wizard/fixtures/operations.py +81 Hot metal gas forming Горячая металла газа формирования
2506 DocType: Sales Order Item Sales Order Date Продажи Порядок Дата
2507 DocType: Sales Invoice Item Delivered Qty Поставляется Кол-во
2508 apps/erpnext/erpnext/stock/doctype/warehouse/warehouse.py +63 Warehouse {0}: Company is mandatory Склад {0}: Компания является обязательным
2509 DocType: Shopping Cart Taxes and Charges Master Shopping Cart Taxes and Charges Master Корзина Налоги и сборы Мастер
2510 apps/erpnext/erpnext/accounts/page/accounts_browser/accounts_browser.js +36 Go to the appropriate group (usually Source of Funds > Current Liabilities > Taxes and Duties and create a new Account (by clicking on Add Child) of type "Tax" and do mention the Tax rate. Перейти к соответствующей группе (обычно источник средств&gt; Краткосрочные обязательства&gt; налогам и сборам и создать новую учетную запись (нажав на Добавить Ребенка) типа &quot;Налог&quot; и упоминают ставка налога.
2511 Payment Period Based On Invoice Date Оплата период на основе Накладная Дата
2796 DocType: Address Plant Завод
2797 apps/frappe/frappe/desk/moduleview.py +64 Setup Настройки
2798 apps/erpnext/erpnext/setup/doctype/supplier_type/supplier_type.js +5 There is nothing to edit. Там нет ничего, чтобы изменить.
2799 apps/erpnext/erpnext/setup/page/setup_wizard/fixtures/operations.py +38 Cold rolling Холодная прокатка
2800 DocType: Customer Group Customer Group Name Группа Имя клиента
2801 apps/erpnext/erpnext/accounts/doctype/sales_invoice/sales_invoice.py +353 Please remove this Invoice {0} from C-Form {1} Пожалуйста, удалите этот счет {0} из C-Form {1}
2802 DocType: Leave Control Panel Please select Carry Forward if you also want to include previous fiscal year's balance leaves to this fiscal year Пожалуйста, выберите переносить, если вы также хотите включить баланс предыдущего финансового года оставляет в этом финансовом году
3063 apps/erpnext/erpnext/accounts/report/payment_period_based_on_invoice_date/payment_period_based_on_invoice_date.py +51 Against Invoice На счета-фактуры
3064 apps/erpnext/erpnext/controllers/trends.py +36 Fiscal Year: {0} does not exists Финансовый год: {0} не существует
3065 DocType: Currency Exchange To Currency В валюту
3066 DocType: Leave Block List Allow the following users to approve Leave Applications for block days. Разрешить следующие пользователи утвердить Leave приложений для блочных дней.
3067 apps/erpnext/erpnext/config/hr.py +155 Types of Expense Claim. Виды Expense претензии.
3068 DocType: Item Taxes Налоги
3069 DocType: Project Default Cost Center По умолчанию Центр Стоимость
3122 DocType: Payment Tool Column Break 1 Разрыв столбца 1
3123 apps/erpnext/erpnext/setup/page/setup_wizard/install_fixtures.py +155 Black Черный
3124 DocType: BOM Explosion Item BOM Explosion Item BOM Взрыв Пункт
3125 DocType: Account Auditor Аудитор
3126 DocType: Purchase Order End date of current order's period Дата окончания периода текущего заказа
3127 apps/erpnext/erpnext/hr/doctype/job_applicant/job_applicant.js +17 Make Offer Letter Сделать предложение письмо
3128 apps/erpnext/erpnext/accounts/doctype/purchase_invoice/purchase_invoice_list.js +10 Return Возвращение
3147 apps/erpnext/erpnext/stock/doctype/stock_ledger_entry/stock_ledger_entry.py +82 Stock cannot exist for Item {0} since has variants Фото существовать не может Пункт {0}, так как имеет варианты
3148 Sales Person-wise Transaction Summary Человек мудрый продаж Общая информация по сделкам
3149 DocType: System Settings Time Zone Часовой Пояс
3150 apps/erpnext/erpnext/stock/doctype/warehouse/warehouse.py +104 Warehouse {0} does not exist Склад {0} не существует
3151 apps/erpnext/erpnext/hub_node/page/hub/register_in_hub.html +2 Register For ERPNext Hub Зарегистрироваться на Hub ERPNext
3152 DocType: Monthly Distribution Monthly Distribution Percentages Ежемесячные Проценты распределения
3153 apps/erpnext/erpnext/stock/doctype/batch/batch.py +16 The selected item cannot have Batch Выбранный элемент не может быть Batch
3232 DocType: Naming Series Select Transaction Выберите операцию
3233 apps/erpnext/erpnext/setup/doctype/authorization_rule/authorization_rule.py +30 Please enter Approving Role or Approving User Пожалуйста, введите утверждении роли или утверждении Пользователь
3234 DocType: Journal Entry Write Off Entry Списание запись
3235 DocType: BOM Rate Of Materials Based On Оценить материалов на основе
3236 apps/erpnext/erpnext/support/page/support_analytics/support_analytics.js +21 Support Analtyics Поддержка Analtyics
3237 DocType: Journal Entry eg. Cheque Number например. Чек Количество
3238 apps/erpnext/erpnext/accounts/doctype/accounts_settings/accounts_settings.py +25 Company is missing in warehouses {0} Компания на складах отсутствует {0}
3530 apps/erpnext/erpnext/config/hr.py +53 Offer candidate a Job. Предложение кандидата Работа.
3531 DocType: Notification Control Prompt for Email on Submission of Запрашивать Email по подаче
3532 apps/erpnext/erpnext/stock/doctype/stock_ledger_entry/stock_ledger_entry.py +68 Item {0} must be a stock Item Пункт {0} должен быть запас товара
3533 apps/erpnext/erpnext/config/accounts.py +107 Default settings for accounting transactions. Настройки по умолчанию для бухгалтерских операций.
3534 apps/frappe/frappe/model/naming.py +40 {0} is required {0} требуется
3535 apps/erpnext/erpnext/setup/page/setup_wizard/fixtures/operations.py +20 Vacuum molding Вакуумная формовка
3536 apps/erpnext/erpnext/stock/doctype/material_request/material_request.py +57 Expected Date cannot be before Material Request Date Ожидаемая дата не может быть до Материал Дата заказа
3822
3823
3824
3825
3826
3827
3828
3849
3850
3851
3852
3853
3854
3855

File diff suppressed because it is too large Load Diff

View File

@ -3334,7 +3334,7 @@ apps/frappe/frappe/core/doctype/user/user.js +134,Loading,Yükleme
DocType: BOM Replace Tool,BOM Replace Tool,BOM Aracı değiştirin
apps/erpnext/erpnext/config/setup.py +37,Country wise default Address Templates,Ülke bilgisi varsayılan adres şablonları
apps/erpnext/erpnext/accounts/party.py +220,Due / Reference Date cannot be after {0},Due / Referans Tarihi sonra olamaz {0}
apps/erpnext/erpnext/config/setup.py +51,Data Import and Export,Veri İthalat ve İhracat
apps/erpnext/erpnext/config/setup.py +51,Data Import and Export,İçeri/Dışarı Aktar
DocType: Features Setup,If you involve in manufacturing activity. Enables Item 'Is Manufactured',Üretim faaliyetlerinde bulunuyorsanız Ürünlerin 'Üretilmiş' olmasını sağlar
DocType: Sales Invoice,Rounded Total,Yuvarlanmış Toplam
DocType: Product Bundle,List items that form the package.,Ambalajı oluşturan Ürünleri listeleyin

1 DocType: Employee Salary Mode Maaş Modu
3334 DocType: Fiscal Year Year Name Yıl Adı
3335 DocType: Fiscal Year Year Name Yıl Adı
3336 DocType: Process Payroll Process Payroll Süreç Bordrosu
3337 apps/erpnext/erpnext/hr/doctype/salary_slip/salary_slip.py +59 There are more holidays than working days this month. Bu ayda çalışma günlerinden daha fazla tatil vardır.
3338 DocType: Product Bundle Item Product Bundle Item Ürün Paketi Ürün
3339 DocType: Sales Partner Sales Partner Name Satış Ortağı Adı
3340 DocType: Sales Partner Sales Partner Name Satış Ortağı Adı

View File

@ -3938,7 +3938,7 @@ DocType: Hub Settings,Seller Name,賣家名稱
DocType: Purchase Invoice,Taxes and Charges Deducted (Company Currency),稅收和扣除(公司貨幣)
DocType: Item Group,General Settings,一般設定
apps/erpnext/erpnext/setup/doctype/currency_exchange/currency_exchange.py +19,From Currency and To Currency cannot be same,原始貨幣和目標貨幣不能相同
DocType: Stock Entry,Repack,
DocType: Stock Entry,Repack,重新包
apps/erpnext/erpnext/setup/doctype/email_digest/email_digest.js +6,You must Save the form before proceeding,在繼續之前,您必須儲存表單
apps/erpnext/erpnext/setup/page/setup_wizard/setup_wizard.js +500,Attach Logo,附加標誌
DocType: Customer,Commission Rate,佣金率

1 DocType: Employee Salary Mode 薪酬模式
3938
3939
3940
3941
3942
3943
3944

View File

@ -17,3 +17,68 @@ def load_address_and_contact(doc, key):
doc.get("__onload").contact_list = frappe.get_all("Contact",
fields="*", filters={key: doc.name},
order_by="is_primary_contact desc, modified desc")
def has_permission(doc, ptype, user):
links = get_permitted_and_not_permitted_links(doc.doctype)
if not links.get("not_permitted_links"):
# optimization: don't determine permissions based on link fields
return True
# True if any one is True or all are empty
names = []
for df in (links.get("permitted_links") + links.get("not_permitted_links")):
doctype = df.options
name = doc.get(df.fieldname)
names.append(name)
if name and frappe.has_permission(doctype, ptype, doc=name):
return True
if not any(names):
return True
else:
return False
def get_permission_query_conditions_for_contact(user):
return get_permission_query_conditions("Contact")
def get_permission_query_conditions_for_address(user):
return get_permission_query_conditions("Address")
def get_permission_query_conditions(doctype):
links = get_permitted_and_not_permitted_links(doctype)
if not links.get("not_permitted_links"):
# when everything is permitted, don't add additional condition
return ""
else:
conditions = []
for df in links.get("permitted_links"):
# like ifnull(customer, '')!='' or ifnull(supplier, '')!=''
conditions.append("ifnull(`tab{doctype}`.`{fieldname}`, '')!=''".format(doctype=doctype, fieldname=df.fieldname))
return "( " + " or ".join(conditions) + " )"
def get_permitted_and_not_permitted_links(doctype):
permitted_links = []
not_permitted_links = []
meta = frappe.get_meta(doctype)
for df in meta.get_link_fields():
if df.options not in ("Customer", "Supplier", "Sales Partner"):
continue
if frappe.has_permission(df.options):
permitted_links.append(df)
else:
not_permitted_links.append(df)
return {
"permitted_links": permitted_links,
"not_permitted_links": not_permitted_links
}

View File

@ -1,6 +1,6 @@
from setuptools import setup, find_packages
version = "6.3.2"
version = "6.4.0"
with open("requirements.txt", "r") as f:
install_requires = f.readlines()