updated translations

This commit is contained in:
Rushabh Mehta 2014-04-16 17:21:25 +05:30
parent 8c51318d82
commit c38fc713c6
35 changed files with 1691 additions and 1049 deletions

View File

@ -39,7 +39,7 @@ class Account(Document):
par = frappe.db.get_value("Account", self.parent_account, par = frappe.db.get_value("Account", self.parent_account,
["name", "group_or_ledger", "report_type"], as_dict=1) ["name", "group_or_ledger", "report_type"], as_dict=1)
if not par: if not par:
throw(_("Parent account does not exists")) throw(_("Parent account does not exist"))
elif par["name"] == self.name: elif par["name"] == self.name:
throw(_("You can not assign itself as parent account")) throw(_("You can not assign itself as parent account"))
elif par["group_or_ledger"] != 'Group': elif par["group_or_ledger"] != 'Group':
@ -117,8 +117,7 @@ class Account(Document):
def validate_warehouse(self, warehouse): def validate_warehouse(self, warehouse):
if frappe.db.get_value("Stock Ledger Entry", {"warehouse": warehouse}): if frappe.db.get_value("Stock Ledger Entry", {"warehouse": warehouse}):
throw(_("Stock transactions exist against warehouse ") + warehouse + throw(_("Stock entries exist against warehouse {0} cannot re-assign or modify 'Master Name'").format(warehouse))
_(" .You can not assign / modify / remove Master Name"))
def update_nsm_model(self): def update_nsm_model(self):
"""update lft, rgt indices for nested set model""" """update lft, rgt indices for nested set model"""
@ -194,7 +193,7 @@ class Account(Document):
# Validate properties before merging # Validate properties before merging
if merge: if merge:
if not frappe.db.exists("Account", new): if not frappe.db.exists("Account", new):
throw(_("Account ") + new +_(" does not exists")) throw(_("Account {0} does not exist").format(new))
val = list(frappe.db.get_value("Account", new_account, val = list(frappe.db.get_value("Account", new_account,
["group_or_ledger", "report_type", "company"])) ["group_or_ledger", "report_type", "company"]))

View File

@ -6,24 +6,23 @@
from __future__ import unicode_literals from __future__ import unicode_literals
import frappe import frappe
from frappe import _ from frappe import _
from frappe.utils import cint from frappe.utils import cint, comma_and
from frappe.model.document import Document from frappe.model.document import Document
class AccountsSettings(Document): class AccountsSettings(Document):
def on_update(self): def on_update(self):
frappe.db.set_default("auto_accounting_for_stock", self.auto_accounting_for_stock) frappe.db.set_default("auto_accounting_for_stock", self.auto_accounting_for_stock)
if cint(self.auto_accounting_for_stock): if cint(self.auto_accounting_for_stock):
# set default perpetual account in company # set default perpetual account in company
for company in frappe.db.sql("select name from tabCompany"): for company in frappe.db.sql("select name from tabCompany"):
frappe.get_doc("Company", company[0]).save() frappe.get_doc("Company", company[0]).save()
# Create account head for warehouses # Create account head for warehouses
warehouse_list = frappe.db.sql("select name, company from tabWarehouse", as_dict=1) warehouse_list = frappe.db.sql("select name, company from tabWarehouse", as_dict=1)
warehouse_with_no_company = [d.name for d in warehouse_list if not d.company] warehouse_with_no_company = [d.name for d in warehouse_list if not d.company]
if warehouse_with_no_company: if warehouse_with_no_company:
frappe.throw(_("Company is missing in following warehouses") + ": \n" + frappe.throw(_("Company is missing in warehouses {0}").format(comma_and(warehouse_with_no_company)))
"\n".join(warehouse_with_no_company))
for wh in warehouse_list: for wh in warehouse_list:
wh_doc = frappe.get_doc("Warehouse", wh.name) wh_doc = frappe.get_doc("Warehouse", wh.name)
wh_doc.save() wh_doc.save()

View File

@ -17,9 +17,9 @@ class BudgetDistribution(Document):
mnth.month = m mnth.month = m
mnth.idx = idx mnth.idx = idx
idx += 1 idx += 1
def validate(self): def validate(self):
total = sum([flt(d.percentage_allocation) for d in self.get("budget_distribution_details")]) total = sum([flt(d.percentage_allocation) for d in self.get("budget_distribution_details")])
if total != 100.0: if total != 100.0:
frappe.throw(_("Percentage Allocation should be equal to ") + "100%") frappe.throw(_("Percentage Allocation should be equal to 100%"))

View File

@ -41,4 +41,4 @@ class FiscalYear(Document):
for fiscal_year, ysd, yed in year_start_end_dates: for fiscal_year, ysd, yed in year_start_end_dates:
if (getdate(self.year_start_date) == ysd and getdate(self.year_end_date) == yed) \ if (getdate(self.year_start_date) == ysd and getdate(self.year_end_date) == yed) \
and (not frappe.flags.in_test): and (not frappe.flags.in_test):
frappe.throw(_("Year Start Date and Year End Date are already set in Fiscal Year: ") + fiscal_year) frappe.throw(_("Year Start Date and Year End Date are already set in Fiscal Year {0}").format(fiscal_year))

View File

@ -33,7 +33,7 @@ class GLEntry(Document):
mandatory = ['account','remarks','voucher_type','voucher_no','fiscal_year','company'] mandatory = ['account','remarks','voucher_type','voucher_no','fiscal_year','company']
for k in mandatory: for k in mandatory:
if not self.get(k): if not self.get(k):
frappe.throw(_("{0} is required").format(k)) frappe.throw(_("{0} is required").format(self.meta.get_label(k)))
# Zero value transaction is not allowed # Zero value transaction is not allowed
if not (flt(self.debit) or flt(self.credit)): if not (flt(self.debit) or flt(self.credit)):

View File

@ -120,17 +120,16 @@ class JournalVoucher(AccountsController):
for d in self.get('entries'): for d in self.get('entries'):
if d.against_invoice and d.credit: if d.against_invoice and d.credit:
currency = frappe.db.get_value("Sales Invoice", d.against_invoice, "currency") currency = frappe.db.get_value("Sales Invoice", d.against_invoice, "currency")
r.append('%s %s against Invoice: %s' % r.append(_("{0} {1} against Invoice {1}").format(currency, fmt_money(flt(d.credit)), d.against_invoice))
(cstr(currency), fmt_money(flt(d.credit)), d.against_invoice))
if d.against_voucher and d.debit: if d.against_voucher and d.debit:
bill_no = frappe.db.sql("""select bill_no, bill_date, currency bill_no = frappe.db.sql("""select bill_no, bill_date, currency
from `tabPurchase Invoice` where name=%s""", d.against_voucher) from `tabPurchase Invoice` where name=%s""", d.against_voucher)
if bill_no and bill_no[0][0] and bill_no[0][0].lower().strip() \ if bill_no and bill_no[0][0] and bill_no[0][0].lower().strip() \
not in ['na', 'not applicable', 'none']: not in ['na', 'not applicable', 'none']:
r.append('%s %s against Bill %s dated %s' % r.append(_('{0} {1} against Bill {2} dated {3}').format(bill_no[0][2],
(cstr(bill_no[0][2]), fmt_money(flt(d.debit)), bill_no[0][0], fmt_money(flt(d.debit)), bill_no[0][0],
bill_no[0][1] and formatdate(bill_no[0][1].strftime('%Y-%m-%d')) or '')) bill_no[0][1] and formatdate(bill_no[0][1].strftime('%Y-%m-%d'))))
if self.user_remark: if self.user_remark:
r.append(_("Note: {0}").format(self.user_remark)) r.append(_("Note: {0}").format(self.user_remark))

View File

@ -3,7 +3,7 @@
from __future__ import unicode_literals from __future__ import unicode_literals
import frappe import frappe
from frappe.utils import cstr, flt from frappe.utils import flt
from frappe import _ from frappe import _
from erpnext.controllers.accounts_controller import AccountsController from erpnext.controllers.accounts_controller import AccountsController
@ -16,37 +16,35 @@ class PeriodClosingVoucher(AccountsController):
self.make_gl_entries() self.make_gl_entries()
def on_cancel(self): def on_cancel(self):
frappe.db.sql("""delete from `tabGL Entry` frappe.db.sql("""delete from `tabGL Entry`
where voucher_type = 'Period Closing Voucher' and voucher_no=%s""", self.name) where voucher_type = 'Period Closing Voucher' and voucher_no=%s""", self.name)
def validate_account_head(self): def validate_account_head(self):
if frappe.db.get_value("Account", self.closing_account_head, "report_type") \ if frappe.db.get_value("Account", self.closing_account_head, "report_type") \
!= "Balance Sheet": != "Balance Sheet":
frappe.throw(_("Account") + ": " + self.closing_account_head + frappe.throw(_("Closing Account {0} must be of type 'Liability'").format(self.closing_account_head))
_("must be a Liability account"))
def validate_posting_date(self): def validate_posting_date(self):
from erpnext.accounts.utils import get_fiscal_year from erpnext.accounts.utils import get_fiscal_year
self.year_start_date = get_fiscal_year(self.posting_date, self.fiscal_year)[1] self.year_start_date = get_fiscal_year(self.posting_date, self.fiscal_year)[1]
pce = frappe.db.sql("""select name from `tabPeriod Closing Voucher` pce = frappe.db.sql("""select name from `tabPeriod Closing Voucher`
where posting_date > %s and fiscal_year = %s and docstatus = 1""", where posting_date > %s and fiscal_year = %s and docstatus = 1""",
(self.posting_date, self.fiscal_year)) (self.posting_date, self.fiscal_year))
if pce and pce[0][0]: if pce and pce[0][0]:
frappe.throw(_("Another Period Closing Entry") + ": " + cstr(pce[0][0]) + frappe.throw(_("Another Period Closing Entry {0} has been made after {1}").format(pce[0][0], self.posting_date))
_("has been made after posting date") + ": " + self.posting_date)
def get_pl_balances(self): def get_pl_balances(self):
"""Get balance for pl accounts""" """Get balance for pl accounts"""
return frappe.db.sql(""" return frappe.db.sql("""
select t1.account, sum(ifnull(t1.debit,0))-sum(ifnull(t1.credit,0)) as balance select t1.account, sum(ifnull(t1.debit,0))-sum(ifnull(t1.credit,0)) as balance
from `tabGL Entry` t1, `tabAccount` t2 from `tabGL Entry` t1, `tabAccount` t2
where t1.account = t2.name and ifnull(t2.report_type, '') = 'Profit and Loss' where t1.account = t2.name and ifnull(t2.report_type, '') = 'Profit and Loss'
and t2.docstatus < 2 and t2.company = %s and t2.docstatus < 2 and t2.company = %s
and t1.posting_date between %s and %s and t1.posting_date between %s and %s
group by t1.account group by t1.account
""", (self.company, self.get("year_start_date"), self.posting_date), as_dict=1) """, (self.company, self.get("year_start_date"), self.posting_date), as_dict=1)
def make_gl_entries(self): def make_gl_entries(self):
gl_entries = [] gl_entries = []
net_pl_balance = 0 net_pl_balance = 0
@ -58,7 +56,7 @@ class PeriodClosingVoucher(AccountsController):
"debit": abs(flt(acc.balance)) if flt(acc.balance) < 0 else 0, "debit": abs(flt(acc.balance)) if flt(acc.balance) < 0 else 0,
"credit": abs(flt(acc.balance)) if flt(acc.balance) > 0 else 0, "credit": abs(flt(acc.balance)) if flt(acc.balance) > 0 else 0,
})) }))
net_pl_balance += flt(acc.balance) net_pl_balance += flt(acc.balance)
if net_pl_balance: if net_pl_balance:
@ -67,6 +65,6 @@ class PeriodClosingVoucher(AccountsController):
"debit": abs(net_pl_balance) if net_pl_balance > 0 else 0, "debit": abs(net_pl_balance) if net_pl_balance > 0 else 0,
"credit": abs(net_pl_balance) if net_pl_balance < 0 else 0 "credit": abs(net_pl_balance) if net_pl_balance < 0 else 0
})) }))
from erpnext.accounts.general_ledger import make_gl_entries from erpnext.accounts.general_ledger import make_gl_entries
make_gl_entries(gl_entries) make_gl_entries(gl_entries)

View File

@ -9,16 +9,15 @@ from frappe import throw, _
from frappe.model.controller import DocListController from frappe.model.controller import DocListController
class PricingRule(DocListController): class PricingRule(DocListController):
def validate(self): def validate(self):
self.validate_mandatory() self.validate_mandatory()
self.cleanup_fields_value() self.cleanup_fields_value()
def validate_mandatory(self): def validate_mandatory(self):
for field in ["apply_on", "applicable_for", "price_or_discount"]: for field in ["apply_on", "applicable_for", "price_or_discount"]:
val = self.get("applicable_for") tocheck = frappe.scrub(self.get(field) or "")
if val and not self.get(frappe.scrub(val)): if tocheck and not self.get(tocheck):
throw(_("{0} is required").format(val), frappe.MandatoryError) throw(_("{0} is required").format(self.meta.get_label(tocheck)), frappe.MandatoryError)
def cleanup_fields_value(self): def cleanup_fields_value(self):
for logic_field in ["apply_on", "applicable_for", "price_or_discount"]: for logic_field in ["apply_on", "applicable_for", "price_or_discount"]:

View File

@ -95,7 +95,7 @@ class PurchaseInvoice(BuyingController):
if not self.remarks and self.bill_date: if not self.remarks and self.bill_date:
self.remarks = (self.remarks or '') + "\n" \ self.remarks = (self.remarks or '') + "\n" \
+ _("Against Bill %s dated %s").format(self.bill_no, formatdate(self.bill_date)) + _("Against Bill {0} dated {1}").format(self.bill_no, formatdate(self.bill_date))
if not self.remarks: if not self.remarks:
self.remarks = "No Remarks" self.remarks = "No Remarks"

View File

@ -85,8 +85,7 @@ def make_entry(args, adv_adj, update_outstanding):
def validate_total_debit_credit(total_debit, total_credit): def validate_total_debit_credit(total_debit, total_credit):
if abs(total_debit - total_credit) > 0.005: if abs(total_debit - total_credit) > 0.005:
frappe.throw(_("Debit and Credit not equal for this voucher: Diff (Debit) is ") + frappe.throw(_("Debit and Credit not equal for this voucher. Difference is {0}.").format(total_debit - total_credit))
cstr(total_debit - total_credit))
def validate_account_for_auto_accounting_for_stock(gl_map): def validate_account_for_auto_accounting_for_stock(gl_map):
if gl_map[0].voucher_type=="Journal Voucher": if gl_map[0].voucher_type=="Journal Voucher":
@ -95,9 +94,7 @@ def validate_account_for_auto_accounting_for_stock(gl_map):
for entry in gl_map: for entry in gl_map:
if entry.account in aii_accounts: if entry.account in aii_accounts:
frappe.throw(_("Account") + ": " + entry.account + frappe.throw(_("Account {0} can only be updated via Stock Transactions"), StockAccountInvalidTransaction)
_(" can only be debited/credited through Stock transactions"),
StockAccountInvalidTransaction)
def delete_gl_entries(gl_entries=None, voucher_type=None, voucher_no=None, def delete_gl_entries(gl_entries=None, voucher_type=None, voucher_no=None,
@ -121,5 +118,5 @@ def delete_gl_entries(gl_entries=None, voucher_type=None, voucher_no=None,
validate_expense_against_budget(entry) validate_expense_against_budget(entry)
if entry.get("against_voucher") and update_outstanding == 'Yes': if entry.get("against_voucher") and update_outstanding == 'Yes':
update_outstanding_amt(entry["account"], entry.get("against_voucher_type"), update_outstanding_amt(entry["account"], entry.get("against_voucher_type"),
entry.get("against_voucher"), on_cancel=True) entry.get("against_voucher"), on_cancel=True)

View File

@ -225,7 +225,7 @@ def remove_against_link_from_jv(ref_type, ref_no, against_field):
and voucher_no != ifnull(against_voucher, '')""", and voucher_no != ifnull(against_voucher, '')""",
(now(), frappe.session.user, ref_type, ref_no)) (now(), frappe.session.user, ref_type, ref_no))
frappe.msgprint(_("Following Journal Vouchers Unlinked: {0}".format("\n".join(linked_jv)))) frappe.msgprint(_("Journal Vouchers {0} are un-linked".format("\n".join(linked_jv))))
@frappe.whitelist() @frappe.whitelist()
@ -233,9 +233,7 @@ def get_company_default(company, fieldname):
value = frappe.db.get_value("Company", company, fieldname) value = frappe.db.get_value("Company", company, fieldname)
if not value: if not value:
throw(_("Please mention default value for '") + throw(_("Please set default value {0} in Company {0}").format(frappe.get_meta("Company").get_label(fieldname), company))
_(frappe.get_meta("Company").get_label(fieldname) +
_("' in Company: ") + company))
return value return value

View File

@ -281,8 +281,7 @@ class SellingController(StockController):
discount = flt(frappe.db.get_value("Item", d.item_code, "max_discount")) discount = flt(frappe.db.get_value("Item", d.item_code, "max_discount"))
if discount and flt(d.discount_percentage) > discount: if discount and flt(d.discount_percentage) > discount:
frappe.throw(_("You cannot give more than ") + cstr(discount) + "% " + frappe.throw(_("Maxiumm discount for Item {0} is {1}%").format(d.item_code, discount))
_("discount on Item Code") + ": " + cstr(d.item_code))
def get_item_list(self): def get_item_list(self):
il = [] il = []
@ -293,8 +292,7 @@ class SellingController(StockController):
if self.doctype == "Sales Order": if self.doctype == "Sales Order":
if (frappe.db.get_value("Item", d.item_code, "is_stock_item") == 'Yes' or if (frappe.db.get_value("Item", d.item_code, "is_stock_item") == 'Yes' or
self.has_sales_bom(d.item_code)) and not d.warehouse: self.has_sales_bom(d.item_code)) and not d.warehouse:
frappe.throw(_("Please enter Reserved Warehouse for item ") + frappe.throw(_("Reserved Warehouse required for stock Item {0} in row {1}").format(d.item, d.idx))
d.item_code + _(" as it is stock Item or packing item"))
reserved_warehouse = d.warehouse reserved_warehouse = d.warehouse
if flt(d.qty) > flt(d.delivered_qty): if flt(d.qty) > flt(d.delivered_qty):
reserved_qty_for_main_item = flt(d.qty) - flt(d.delivered_qty) reserved_qty_for_main_item = flt(d.qty) - flt(d.delivered_qty)
@ -373,7 +371,7 @@ def check_active_sales_items(obj):
is_service_item, income_account from tabItem where name = %s""", is_service_item, income_account from tabItem where name = %s""",
d.item_code, as_dict=True)[0] d.item_code, as_dict=True)[0]
if item.is_sales_item == 'No' and item.is_service_item == 'No': if item.is_sales_item == 'No' and item.is_service_item == 'No':
frappe.throw(_("Item is neither Sales nor Service Item") + ": " + d.item_code) frappe.throw(_("Item {0} must be Sales or Service Item in {1}").format(d.item_code, d.idx))
if getattr(d, "income_account", None) and not item.income_account: if getattr(d, "income_account", None) and not item.income_account:
frappe.db.set_value("Item", d.item_code, "income_account", frappe.db.set_value("Item", d.item_code, "income_account",
d.income_account) d.income_account)

View File

@ -45,6 +45,8 @@ class StockController(AccountsController):
for sle in sle_list: for sle in sle_list:
if warehouse_account.get(sle.warehouse): if warehouse_account.get(sle.warehouse):
# from warehouse account # from warehouse account
self.check_expense_account(detail)
gl_list.append(self.get_gl_dict({ gl_list.append(self.get_gl_dict({
"account": warehouse_account[sle.warehouse], "account": warehouse_account[sle.warehouse],
"against": detail.expense_account, "against": detail.expense_account,
@ -73,8 +75,6 @@ class StockController(AccountsController):
def get_voucher_details(self, stock_ledger, default_expense_account, default_cost_center): def get_voucher_details(self, stock_ledger, default_expense_account, default_cost_center):
if not default_expense_account: if not default_expense_account:
details = self.get(self.fname) details = self.get(self.fname)
for d in details:
self.check_expense_account(d)
else: else:
details = [frappe._dict({ details = [frappe._dict({
"name":d, "name":d,
@ -231,10 +231,10 @@ class StockController(AccountsController):
def check_expense_account(self, item): def check_expense_account(self, item):
if item.meta.get_field("expense_account") and not item.expense_account: if item.meta.get_field("expense_account") and not item.expense_account:
frappe.throw(_("Expense or Difference account is mandatory for Item {0}").format(item.item_code)) frappe.throw(_("Expense or Difference account is mandatory for Item {0} as there is difference in value").format(item.item_code))
if item.meta.get_field("expense_account") and not item.cost_center: if getattr(item, "expense_account", None) and not item.cost_center:
frappe.throw(_("""Cost Center is mandatory for item {0}""").format(item.item_code)) frappe.throw(_("""Cost Center is mandatory for Item {0}""").format(item.item_code))
def get_sl_entries(self, d, args): def get_sl_entries(self, d, args):
sl_dict = { sl_dict = {

View File

@ -6,10 +6,6 @@ import frappe
from frappe.utils import cint, cstr, flt, nowdate, comma_and from frappe.utils import cint, cstr, flt, nowdate, comma_and
from frappe import msgprint, _ from frappe import msgprint, _
from frappe.model.document import Document from frappe.model.document import Document
class LeaveControlPanel(Document): class LeaveControlPanel(Document):
@ -33,7 +29,7 @@ class LeaveControlPanel(Document):
def validate_values(self): def validate_values(self):
for f in ["fiscal_year", "leave_type", "no_of_days"]: for f in ["fiscal_year", "leave_type", "no_of_days"]:
if not self.get(f): if not self.get(f):
frappe.throw(_(self.meta.get_label(f)) + _(" is mandatory")) frappe.throw(_("{0} is required").format(self.meta.get_label(f)))
def allocate_leave(self): def allocate_leave(self):
self.validate_values() self.validate_values()

View File

@ -4,7 +4,7 @@
var display_activity_log = function(msg) { var display_activity_log = function(msg) {
if(!pscript.ss_html) if(!pscript.ss_html)
pscript.ss_html = $a(cur_frm.fields_dict['activity_log'].wrapper,'div'); pscript.ss_html = $a(cur_frm.fields_dict['activity_log'].wrapper,'div');
pscript.ss_html.innerHTML = pscript.ss_html.innerHTML =
'<div class="panel"><div class="panel-heading">'+__("Activity Log:")+'</div>'+msg+'</div>'; '<div class="panel"><div class="panel-heading">'+__("Activity Log:")+'</div>'+msg+'</div>';
} }
@ -19,7 +19,7 @@ cur_frm.cscript.create_salary_slip = function(doc, cdt, cdn) {
} }
cur_frm.cscript.submit_salary_slip = function(doc, cdt, cdn) { cur_frm.cscript.submit_salary_slip = function(doc, cdt, cdn) {
var check = confirm(__("Do you really want to Submit all Salary Slip for month : ") + doc.month+ __(" and fiscal year : ")+doc.fiscal_year); var check = confirm(__("Do you really want to Submit all Salary Slip for month {0} and year {1}", [doc.month, doc.fiscal_year]));
if(check){ if(check){
var callback = function(r, rt){ var callback = function(r, rt){
if (r.message) if (r.message)
@ -42,8 +42,7 @@ cur_frm.cscript.make_jv = function(doc, dt, dn) {
var jv = frappe.model.make_new_doc_and_get_name('Journal Voucher'); var jv = frappe.model.make_new_doc_and_get_name('Journal Voucher');
jv = locals['Journal Voucher'][jv]; jv = locals['Journal Voucher'][jv];
jv.voucher_type = 'Bank Voucher'; jv.voucher_type = 'Bank Voucher';
jv.user_remark = __('Payment of salary for the month: ') + doc.month + jv.user_remark = __('Payment of salary for the month {0} and year {1}', [doc.month, doc.fiscal_year]);
__(' and fiscal year: ') + doc.fiscal_year;
jv.fiscal_year = doc.fiscal_year; jv.fiscal_year = doc.fiscal_year;
jv.company = doc.company; jv.company = doc.company;
jv.posting_date = dateutil.obj_to_str(new Date()); jv.posting_date = dateutil.obj_to_str(new Date());

View File

@ -180,7 +180,7 @@ class BOM(Document):
""" Validate main FG item""" """ Validate main FG item"""
item = self.get_item_det(self.item) item = self.get_item_det(self.item)
if not item: if not item:
frappe.throw(_("Item {0} does not exists in the system or has expired").format(self.item)) frappe.throw(_("Item {0} does not exist in the system or has expired").format(self.item))
elif item[0]['is_manufactured_item'] != 'Yes' \ elif item[0]['is_manufactured_item'] != 'Yes' \
and item[0]['is_sub_contracted_item'] != 'Yes': and item[0]['is_sub_contracted_item'] != 'Yes':
frappe.throw(_("Item {0} must be manufactured or sub-contracted").format(self.item)) frappe.throw(_("Item {0} must be manufactured or sub-contracted").format(self.item))

View File

@ -1,234 +1,667 @@
{ {
"_last_update": null,
"_user_tags": null,
"allow_attach": null,
"allow_copy": null,
"allow_email": null,
"allow_import": 1, "allow_import": 1,
"allow_print": null,
"allow_rename": null,
"allow_trash": null,
"autoname": "naming_series:", "autoname": "naming_series:",
"creation": "2013-01-10 16:34:16.000000", "change_log": null,
"client_script": null,
"client_script_core": null,
"client_string": null,
"colour": null,
"creation": "2013-01-10 16:34:16",
"custom": null,
"default_print_format": null,
"description": null,
"docstatus": 0, "docstatus": 0,
"doctype": "DocType", "doctype": "DocType",
"document_type": null,
"dt_template": null,
"fields": [ "fields": [
{ {
"allow_on_submit": null,
"default": null,
"depends_on": null,
"description": null,
"fieldname": "item", "fieldname": "item",
"fieldtype": "Section Break", "fieldtype": "Section Break",
"hidden": null,
"ignore_restrictions": null,
"in_filter": null,
"in_list_view": null,
"label": "Item", "label": "Item",
"no_column": null,
"no_copy": null,
"oldfieldname": null,
"oldfieldtype": null,
"options": "icon-gift", "options": "icon-gift",
"permlevel": 0 "permlevel": 0,
"print_hide": null,
"print_width": null,
"read_only": null,
"report_hide": null,
"reqd": null,
"search_index": null,
"set_only_once": null,
"trigger": null,
"width": null
}, },
{ {
"allow_on_submit": null,
"default": "PRO", "default": "PRO",
"depends_on": null,
"description": null,
"fieldname": "naming_series", "fieldname": "naming_series",
"fieldtype": "Select", "fieldtype": "Select",
"hidden": null,
"ignore_restrictions": null,
"in_filter": null,
"in_list_view": null,
"label": "Series", "label": "Series",
"no_column": null,
"no_copy": null,
"oldfieldname": null,
"oldfieldtype": null,
"options": "\nPRO", "options": "\nPRO",
"permlevel": 0, "permlevel": 0,
"reqd": 1 "print_hide": null,
}, "print_width": null,
{ "read_only": null,
"fieldname": "production_item", "report_hide": null,
"fieldtype": "Link", "reqd": 1,
"in_filter": 1, "search_index": null,
"in_list_view": 1, "set_only_once": null,
"label": "Item To Manufacture", "trigger": null,
"oldfieldname": "production_item", "width": null
"oldfieldtype": "Link",
"options": "Item",
"permlevel": 0,
"read_only": 0,
"reqd": 1
},
{
"depends_on": "production_item",
"description": "Bill of Material to be considered for manufacturing",
"fieldname": "bom_no",
"fieldtype": "Link",
"in_list_view": 1,
"label": "BOM No",
"oldfieldname": "bom_no",
"oldfieldtype": "Link",
"options": "BOM",
"permlevel": 0,
"read_only": 0,
"reqd": 1
},
{
"default": "1",
"description": "If checked, BOM for sub-assembly items will be considered for getting raw materials. Otherwise, all sub-assembly items will be treated as a raw material.",
"fieldname": "use_multi_level_bom",
"fieldtype": "Check",
"label": "Use Multi-Level BOM",
"permlevel": 0
},
{
"fieldname": "column_break1",
"fieldtype": "Column Break",
"oldfieldtype": "Column Break",
"permlevel": 0,
"read_only": 0,
"width": "50%"
},
{
"description": "Manufacture against Sales Order",
"fieldname": "sales_order",
"fieldtype": "Link",
"label": "Sales Order",
"options": "Sales Order",
"permlevel": 0,
"read_only": 0
},
{
"depends_on": "production_item",
"fieldname": "qty",
"fieldtype": "Float",
"in_list_view": 1,
"label": "Qty To Manufacture",
"oldfieldname": "qty",
"oldfieldtype": "Currency",
"permlevel": 0,
"read_only": 0,
"reqd": 1
},
{
"depends_on": "eval:doc.docstatus==1",
"description": "Automatically updated via Stock Entry of type Manufacture/Repack",
"fieldname": "produced_qty",
"fieldtype": "Float",
"label": "Manufactured Qty",
"no_copy": 1,
"oldfieldname": "produced_qty",
"oldfieldtype": "Currency",
"permlevel": 0,
"read_only": 1
},
{
"depends_on": "sales_order",
"fieldname": "expected_delivery_date",
"fieldtype": "Date",
"label": "Expected Delivery Date",
"permlevel": 0,
"read_only": 1
},
{
"fieldname": "warehouses",
"fieldtype": "Section Break",
"label": "Warehouses",
"options": "icon-building",
"permlevel": 0
},
{
"depends_on": "production_item",
"description": "Manufactured quantity will be updated in this warehouse",
"fieldname": "fg_warehouse",
"fieldtype": "Link",
"in_list_view": 1,
"label": "For Warehouse",
"options": "Warehouse",
"permlevel": 0,
"read_only": 0,
"reqd": 0
},
{
"fieldname": "column_break_12",
"fieldtype": "Column Break",
"permlevel": 0
},
{
"fieldname": "wip_warehouse",
"fieldtype": "Link",
"label": "Work-in-Progress Warehouse",
"options": "Warehouse",
"permlevel": 0,
"reqd": 0
},
{
"fieldname": "more_info",
"fieldtype": "Section Break",
"label": "More Info",
"options": "icon-file-text",
"permlevel": 0,
"read_only": 0
}, },
{ {
"allow_on_submit": null,
"default": null,
"depends_on": "eval:!doc.__islocal", "depends_on": "eval:!doc.__islocal",
"description": null,
"fieldname": "status", "fieldname": "status",
"fieldtype": "Select", "fieldtype": "Select",
"hidden": null,
"ignore_restrictions": null,
"in_filter": 1, "in_filter": 1,
"in_list_view": 1, "in_list_view": 1,
"label": "Status", "label": "Status",
"no_column": null,
"no_copy": 1, "no_copy": 1,
"oldfieldname": "status", "oldfieldname": "status",
"oldfieldtype": "Select", "oldfieldtype": "Select",
"options": "\nDraft\nSubmitted\nStopped\nIn Process\nCompleted\nCancelled", "options": "\nDraft\nSubmitted\nStopped\nIn Process\nCompleted\nCancelled",
"permlevel": 0, "permlevel": 0,
"print_hide": null,
"print_width": null,
"read_only": 1, "read_only": 1,
"report_hide": null,
"reqd": 1, "reqd": 1,
"search_index": 1 "search_index": 1,
"set_only_once": null,
"trigger": null,
"width": null
}, },
{ {
"allow_on_submit": null,
"default": null,
"depends_on": null,
"description": null,
"fieldname": "production_item",
"fieldtype": "Link",
"hidden": null,
"ignore_restrictions": null,
"in_filter": 1,
"in_list_view": 1,
"label": "Item To Manufacture",
"no_column": null,
"no_copy": null,
"oldfieldname": "production_item",
"oldfieldtype": "Link",
"options": "Item",
"permlevel": 0,
"print_hide": null,
"print_width": null,
"read_only": 0,
"report_hide": null,
"reqd": 1,
"search_index": null,
"set_only_once": null,
"trigger": null,
"width": null
},
{
"allow_on_submit": null,
"default": null,
"depends_on": "production_item",
"description": "Bill of Material to be considered for manufacturing",
"fieldname": "bom_no",
"fieldtype": "Link",
"hidden": null,
"ignore_restrictions": null,
"in_filter": null,
"in_list_view": 1,
"label": "BOM No",
"no_column": null,
"no_copy": null,
"oldfieldname": "bom_no",
"oldfieldtype": "Link",
"options": "BOM",
"permlevel": 0,
"print_hide": null,
"print_width": null,
"read_only": 0,
"report_hide": null,
"reqd": 1,
"search_index": null,
"set_only_once": null,
"trigger": null,
"width": null
},
{
"allow_on_submit": null,
"default": "1",
"depends_on": null,
"description": "If checked, BOM for sub-assembly items will be considered for getting raw materials. Otherwise, all sub-assembly items will be treated as a raw material.",
"fieldname": "use_multi_level_bom",
"fieldtype": "Check",
"hidden": null,
"ignore_restrictions": null,
"in_filter": null,
"in_list_view": null,
"label": "Use Multi-Level BOM",
"no_column": null,
"no_copy": null,
"oldfieldname": null,
"oldfieldtype": null,
"options": null,
"permlevel": 0,
"print_hide": null,
"print_width": null,
"read_only": null,
"report_hide": null,
"reqd": null,
"search_index": null,
"set_only_once": null,
"trigger": null,
"width": null
},
{
"allow_on_submit": null,
"default": null,
"depends_on": null,
"description": null,
"fieldname": "column_break1",
"fieldtype": "Column Break",
"hidden": null,
"ignore_restrictions": null,
"in_filter": null,
"in_list_view": null,
"label": null,
"no_column": null,
"no_copy": null,
"oldfieldname": null,
"oldfieldtype": "Column Break",
"options": null,
"permlevel": 0,
"print_hide": null,
"print_width": null,
"read_only": 0,
"report_hide": null,
"reqd": null,
"search_index": null,
"set_only_once": null,
"trigger": null,
"width": "50%"
},
{
"allow_on_submit": null,
"default": null,
"depends_on": null,
"description": "Manufacture against Sales Order",
"fieldname": "sales_order",
"fieldtype": "Link",
"hidden": null,
"ignore_restrictions": null,
"in_filter": null,
"in_list_view": null,
"label": "Sales Order",
"no_column": null,
"no_copy": null,
"oldfieldname": null,
"oldfieldtype": null,
"options": "Sales Order",
"permlevel": 0,
"print_hide": null,
"print_width": null,
"read_only": 0,
"report_hide": null,
"reqd": null,
"search_index": null,
"set_only_once": null,
"trigger": null,
"width": null
},
{
"allow_on_submit": null,
"default": null,
"depends_on": "production_item",
"description": null,
"fieldname": "qty",
"fieldtype": "Float",
"hidden": null,
"ignore_restrictions": null,
"in_filter": null,
"in_list_view": 1,
"label": "Qty To Manufacture",
"no_column": null,
"no_copy": null,
"oldfieldname": "qty",
"oldfieldtype": "Currency",
"options": null,
"permlevel": 0,
"print_hide": null,
"print_width": null,
"read_only": 0,
"report_hide": null,
"reqd": 1,
"search_index": null,
"set_only_once": null,
"trigger": null,
"width": null
},
{
"allow_on_submit": null,
"default": null,
"depends_on": "eval:doc.docstatus==1",
"description": "Automatically updated via Stock Entry of type Manufacture/Repack",
"fieldname": "produced_qty",
"fieldtype": "Float",
"hidden": null,
"ignore_restrictions": null,
"in_filter": null,
"in_list_view": null,
"label": "Manufactured Qty",
"no_column": null,
"no_copy": 1,
"oldfieldname": "produced_qty",
"oldfieldtype": "Currency",
"options": null,
"permlevel": 0,
"print_hide": null,
"print_width": null,
"read_only": 1,
"report_hide": null,
"reqd": null,
"search_index": null,
"set_only_once": null,
"trigger": null,
"width": null
},
{
"allow_on_submit": null,
"default": null,
"depends_on": "sales_order",
"description": null,
"fieldname": "expected_delivery_date",
"fieldtype": "Date",
"hidden": null,
"ignore_restrictions": null,
"in_filter": null,
"in_list_view": null,
"label": "Expected Delivery Date",
"no_column": null,
"no_copy": null,
"oldfieldname": null,
"oldfieldtype": null,
"options": null,
"permlevel": 0,
"print_hide": null,
"print_width": null,
"read_only": 1,
"report_hide": null,
"reqd": null,
"search_index": null,
"set_only_once": null,
"trigger": null,
"width": null
},
{
"allow_on_submit": null,
"default": null,
"depends_on": null,
"description": null,
"fieldname": "warehouses",
"fieldtype": "Section Break",
"hidden": null,
"ignore_restrictions": null,
"in_filter": null,
"in_list_view": null,
"label": "Warehouses",
"no_column": null,
"no_copy": null,
"oldfieldname": null,
"oldfieldtype": null,
"options": "icon-building",
"permlevel": 0,
"print_hide": null,
"print_width": null,
"read_only": null,
"report_hide": null,
"reqd": null,
"search_index": null,
"set_only_once": null,
"trigger": null,
"width": null
},
{
"allow_on_submit": null,
"default": null,
"depends_on": "production_item",
"description": "Manufactured quantity will be updated in this warehouse",
"fieldname": "fg_warehouse",
"fieldtype": "Link",
"hidden": null,
"ignore_restrictions": null,
"in_filter": null,
"in_list_view": 0,
"label": "For Warehouse",
"no_column": null,
"no_copy": null,
"oldfieldname": null,
"oldfieldtype": null,
"options": "Warehouse",
"permlevel": 0,
"print_hide": null,
"print_width": null,
"read_only": 0,
"report_hide": null,
"reqd": 0,
"search_index": null,
"set_only_once": null,
"trigger": null,
"width": null
},
{
"allow_on_submit": null,
"default": null,
"depends_on": null,
"description": null,
"fieldname": "column_break_12",
"fieldtype": "Column Break",
"hidden": null,
"ignore_restrictions": null,
"in_filter": null,
"in_list_view": null,
"label": null,
"no_column": null,
"no_copy": null,
"oldfieldname": null,
"oldfieldtype": null,
"options": null,
"permlevel": 0,
"print_hide": null,
"print_width": null,
"read_only": null,
"report_hide": null,
"reqd": null,
"search_index": null,
"set_only_once": null,
"trigger": null,
"width": null
},
{
"allow_on_submit": null,
"default": null,
"depends_on": null,
"description": null,
"fieldname": "wip_warehouse",
"fieldtype": "Link",
"hidden": null,
"ignore_restrictions": null,
"in_filter": null,
"in_list_view": null,
"label": "Work-in-Progress Warehouse",
"no_column": null,
"no_copy": null,
"oldfieldname": null,
"oldfieldtype": null,
"options": "Warehouse",
"permlevel": 0,
"print_hide": null,
"print_width": null,
"read_only": null,
"report_hide": null,
"reqd": 0,
"search_index": null,
"set_only_once": null,
"trigger": null,
"width": null
},
{
"allow_on_submit": null,
"default": null,
"depends_on": null,
"description": null,
"fieldname": "more_info",
"fieldtype": "Section Break",
"hidden": null,
"ignore_restrictions": null,
"in_filter": null,
"in_list_view": null,
"label": "More Info",
"no_column": null,
"no_copy": null,
"oldfieldname": null,
"oldfieldtype": null,
"options": "icon-file-text",
"permlevel": 0,
"print_hide": null,
"print_width": null,
"read_only": 0,
"report_hide": null,
"reqd": null,
"search_index": null,
"set_only_once": null,
"trigger": null,
"width": null
},
{
"allow_on_submit": null,
"default": null,
"depends_on": null,
"description": null,
"fieldname": "description", "fieldname": "description",
"fieldtype": "Small Text", "fieldtype": "Small Text",
"hidden": null,
"ignore_restrictions": null,
"in_filter": null,
"in_list_view": null,
"label": "Item Description", "label": "Item Description",
"no_column": null,
"no_copy": null,
"oldfieldname": null,
"oldfieldtype": null,
"options": null,
"permlevel": 0, "permlevel": 0,
"read_only": 1 "print_hide": null,
"print_width": null,
"read_only": 1,
"report_hide": null,
"reqd": null,
"search_index": null,
"set_only_once": null,
"trigger": null,
"width": null
}, },
{ {
"allow_on_submit": null,
"default": null,
"depends_on": null,
"description": null,
"fieldname": "project_name", "fieldname": "project_name",
"fieldtype": "Link", "fieldtype": "Link",
"hidden": null,
"ignore_restrictions": null,
"in_filter": 1, "in_filter": 1,
"in_list_view": null,
"label": "Project Name", "label": "Project Name",
"no_column": null,
"no_copy": null,
"oldfieldname": "project_name", "oldfieldname": "project_name",
"oldfieldtype": "Link", "oldfieldtype": "Link",
"options": "Project", "options": "Project",
"permlevel": 0, "permlevel": 0,
"read_only": 0 "print_hide": null,
"print_width": null,
"read_only": 0,
"report_hide": null,
"reqd": null,
"search_index": null,
"set_only_once": null,
"trigger": null,
"width": null
}, },
{ {
"allow_on_submit": null,
"default": null,
"depends_on": null,
"description": null,
"fieldname": "column_break2", "fieldname": "column_break2",
"fieldtype": "Column Break", "fieldtype": "Column Break",
"hidden": null,
"ignore_restrictions": null,
"in_filter": null,
"in_list_view": null,
"label": null,
"no_column": null,
"no_copy": null,
"oldfieldname": null,
"oldfieldtype": null,
"options": null,
"permlevel": 0, "permlevel": 0,
"print_hide": null,
"print_width": null,
"read_only": 0, "read_only": 0,
"report_hide": null,
"reqd": null,
"search_index": null,
"set_only_once": null,
"trigger": null,
"width": "50%" "width": "50%"
}, },
{ {
"allow_on_submit": null,
"default": null,
"depends_on": "production_item", "depends_on": "production_item",
"description": null,
"fieldname": "stock_uom", "fieldname": "stock_uom",
"fieldtype": "Link", "fieldtype": "Link",
"hidden": null,
"ignore_restrictions": null,
"in_filter": null,
"in_list_view": null,
"label": "Stock UOM", "label": "Stock UOM",
"no_column": null,
"no_copy": null,
"oldfieldname": "stock_uom", "oldfieldname": "stock_uom",
"oldfieldtype": "Data", "oldfieldtype": "Data",
"options": "UOM", "options": "UOM",
"permlevel": 0, "permlevel": 0,
"read_only": 1 "print_hide": null,
"print_width": null,
"read_only": 1,
"report_hide": null,
"reqd": null,
"search_index": null,
"set_only_once": null,
"trigger": null,
"width": null
}, },
{ {
"allow_on_submit": null,
"default": null,
"depends_on": null,
"description": null,
"fieldname": "company", "fieldname": "company",
"fieldtype": "Link", "fieldtype": "Link",
"hidden": null,
"ignore_restrictions": null,
"in_filter": null,
"in_list_view": null,
"label": "Company", "label": "Company",
"no_column": null,
"no_copy": null,
"oldfieldname": "company", "oldfieldname": "company",
"oldfieldtype": "Link", "oldfieldtype": "Link",
"options": "Company", "options": "Company",
"permlevel": 0, "permlevel": 0,
"print_hide": null,
"print_width": null,
"read_only": 0, "read_only": 0,
"reqd": 1 "report_hide": null,
"reqd": 1,
"search_index": null,
"set_only_once": null,
"trigger": null,
"width": null
}, },
{ {
"allow_on_submit": null,
"default": null,
"depends_on": null,
"description": null,
"fieldname": "amended_from", "fieldname": "amended_from",
"fieldtype": "Data", "fieldtype": "Data",
"hidden": null,
"ignore_restrictions": 1, "ignore_restrictions": 1,
"in_filter": null,
"in_list_view": null,
"label": "Amended From", "label": "Amended From",
"no_column": null,
"no_copy": 1, "no_copy": 1,
"oldfieldname": "amended_from", "oldfieldname": "amended_from",
"oldfieldtype": "Data", "oldfieldtype": "Data",
"options": null,
"permlevel": 0, "permlevel": 0,
"read_only": 1 "print_hide": null,
"print_width": null,
"read_only": 1,
"report_hide": null,
"reqd": null,
"search_index": null,
"set_only_once": null,
"trigger": null,
"width": null
} }
], ],
"hide_heading": null,
"hide_toolbar": null,
"icon": "icon-cogs", "icon": "icon-cogs",
"idx": 1, "idx": 1,
"in_create": 0, "in_create": 0,
"in_dialog": null,
"is_submittable": 1, "is_submittable": 1,
"modified": "2014-01-20 17:49:01.000000", "is_transaction_doc": null,
"issingle": null,
"istable": null,
"max_attachments": null,
"menu_index": null,
"modified": "2014-04-16 11:31:11.764385",
"modified_by": "Administrator", "modified_by": "Administrator",
"module": "Manufacturing", "module": "Manufacturing",
"name": "Production Order", "name": "Production Order",
"name_case": null,
"owner": "Administrator", "owner": "Administrator",
"parent": null,
"parent_node": null,
"parentfield": null,
"parenttype": null,
"permissions": [ "permissions": [
{ {
"amend": 1, "amend": 1,
@ -236,13 +669,35 @@
"create": 1, "create": 1,
"delete": 1, "delete": 1,
"email": 1, "email": 1,
"export": null,
"import": null,
"match": null,
"permlevel": 0, "permlevel": 0,
"print": 1, "print": 1,
"read": 1, "read": 1,
"report": 1, "report": 1,
"restrict": null,
"restricted": null,
"role": "Manufacturing User", "role": "Manufacturing User",
"submit": 1, "submit": 1,
"write": 1 "write": 1
} }
] ],
"plugin": null,
"print_outline": null,
"read_only": null,
"read_only_onload": null,
"search_fields": null,
"section_style": null,
"server_code": null,
"server_code_compiled": null,
"server_code_core": null,
"server_code_error": null,
"show_in_menu": null,
"smallicon": null,
"subject": null,
"tag_fields": null,
"title_field": null,
"use_template": null,
"version": null
} }

View File

@ -4,7 +4,7 @@
from __future__ import unicode_literals from __future__ import unicode_literals
import frappe import frappe
from frappe.utils import cstr, flt, nowdate from frappe.utils import flt, nowdate
from frappe import _ from frappe import _
from frappe.model.document import Document from frappe.model.document import Document
@ -75,11 +75,8 @@ class ProductionOrder(Document):
so_qty = flt(so_item_qty) + flt(dnpi_qty) so_qty = flt(so_item_qty) + flt(dnpi_qty)
if total_qty > so_qty: if total_qty > so_qty:
frappe.throw(_("Total production order qty for item") + ": " + frappe.throw(_("Cannot produce more Item {0} than Sales Order quantity {1}").format(self.production_item,
cstr(self.production_item) + _(" against sales order") + ": " + so_qty), OverProductionError)
cstr(self.sales_order) + _(" will be ") + cstr(total_qty) + ", " +
_("which is greater than sales order qty ") + "(" + cstr(so_qty) + ")" +
_("Please reduce qty."), exc=OverProductionError)
def stop_unstop(self, status): def stop_unstop(self, status):
""" Called from client side on Stop/Unstop event""" """ Called from client side on Stop/Unstop event"""
@ -115,7 +112,7 @@ class ProductionOrder(Document):
produced_qty = flt(produced_qty[0][0]) if produced_qty else 0 produced_qty = flt(produced_qty[0][0]) if produced_qty else 0
if produced_qty > self.qty: if produced_qty > self.qty:
frappe.throw(_("Cannot manufacture more than the planned Quantity to Manufacture ({0}) in Production Order: {1}").format(self.qty, self.name), StockOverProductionError) frappe.throw(_("Manufactured quantity {0} cannot be greater than planned quanitity {1} in Production Order {2}").format(produced_qty, self.qty, self.name, StockOverProductionError))
self.db_set("produced_qty", produced_qty) self.db_set("produced_qty", produced_qty)
@ -167,7 +164,7 @@ def get_item_details(item):
return res return res
@frappe.whitelist() @frappe.whitelist()
def make_stock_entry(production_order_id, purpose): def make_stock_entry(production_order_id, purpose, qty=None):
production_order = frappe.get_doc("Production Order", production_order_id) production_order = frappe.get_doc("Production Order", production_order_id)
stock_entry = frappe.new_doc("Stock Entry") stock_entry = frappe.new_doc("Stock Entry")
@ -176,7 +173,7 @@ def make_stock_entry(production_order_id, purpose):
stock_entry.company = production_order.company stock_entry.company = production_order.company
stock_entry.bom_no = production_order.bom_no stock_entry.bom_no = production_order.bom_no
stock_entry.use_multi_level_bom = production_order.use_multi_level_bom stock_entry.use_multi_level_bom = production_order.use_multi_level_bom
stock_entry.fg_completed_qty = flt(production_order.qty) - flt(production_order.produced_qty) stock_entry.fg_completed_qty = qty or (flt(production_order.qty) - flt(production_order.produced_qty))
if purpose=="Material Transfer": if purpose=="Material Transfer":
stock_entry.to_warehouse = production_order.wip_warehouse stock_entry.to_warehouse = production_order.wip_warehouse

View File

@ -5,7 +5,6 @@
from __future__ import unicode_literals from __future__ import unicode_literals
import unittest import unittest
import frappe import frappe
from frappe.utils import cstr, getdate
from erpnext.stock.doctype.purchase_receipt.test_purchase_receipt import set_perpetual_inventory from erpnext.stock.doctype.purchase_receipt.test_purchase_receipt import set_perpetual_inventory
from erpnext.manufacturing.doctype.production_order.production_order import make_stock_entry from erpnext.manufacturing.doctype.production_order.production_order import make_stock_entry
@ -13,56 +12,69 @@ from erpnext.manufacturing.doctype.production_order.production_order import make
class TestProductionOrder(unittest.TestCase): class TestProductionOrder(unittest.TestCase):
def test_planned_qty(self): def test_planned_qty(self):
set_perpetual_inventory(0) set_perpetual_inventory(0)
frappe.db.sql("delete from `tabStock Ledger Entry`")
frappe.db.sql("""delete from `tabBin`""")
frappe.db.sql("""delete from `tabGL Entry`""")
pro_doc = frappe.copy_doc(test_records[0]) pro_doc = frappe.copy_doc(test_records[0])
pro_doc.insert() pro_doc.insert()
pro_doc.submit() pro_doc.submit()
from erpnext.stock.doctype.stock_entry.test_stock_entry import test_records as se_test_records # add raw materials to stores
mr1 = frappe.copy_doc(se_test_records[0]) s = frappe.new_doc("Stock Entry")
mr1.insert() s.purpose = "Material Receipt"
mr1.submit() s.company = "_Test Company"
s.append("mtn_details", {
"item_code": "_Test Item",
"t_warehouse": "Stores - _TC",
"qty": 100,
"incoming_rate": 5000
})
s.insert()
s.submit()
mr2 = frappe.copy_doc(se_test_records[0]) # add raw materials to stores
mr2.get("mtn_details")[0].item_code = "_Test Item Home Desktop 100" s = frappe.new_doc("Stock Entry")
mr2.insert() s.purpose = "Material Receipt"
mr2.submit() s.company = "_Test Company"
s.append("mtn_details", {
"item_code": "_Test Item Home Desktop 100",
"t_warehouse": "Stores - _TC",
"qty": 100,
"incoming_rate": 1000
})
s.insert()
s.submit()
stock_entry = make_stock_entry(pro_doc.name, "Manufacture/Repack") # from stores to wip
stock_entry = frappe.get_doc(stock_entry) s = frappe.get_doc(make_stock_entry(pro_doc.name, "Material Transfer", 4))
stock_entry.fiscal_year = "_Test Fiscal Year 2013" for d in s.get("mtn_details"):
stock_entry.fg_completed_qty = 4 d.s_warehouse = "Stores - _TC"
stock_entry.posting_date = "2013-05-12" s.insert()
stock_entry.fiscal_year = "_Test Fiscal Year 2013" s.submit()
stock_entry.set("mtn_details", [])
stock_entry.run_method("get_items") # from wip to fg
stock_entry.submit() s = frappe.get_doc(make_stock_entry(pro_doc.name, "Manufacture/Repack", 4))
s.insert()
s.submit()
self.assertEqual(frappe.db.get_value("Production Order", pro_doc.name, self.assertEqual(frappe.db.get_value("Production Order", pro_doc.name,
"produced_qty"), 4) "produced_qty"), 4)
self.assertEqual(frappe.db.get_value("Bin", {"item_code": "_Test FG Item", self.assertEqual(frappe.db.get_value("Bin", {"item_code": "_Test FG Item",
"warehouse": "_Test Warehouse 1 - _TC"}, "planned_qty"), 6) "warehouse": "_Test Warehouse 1 - _TC"}, "planned_qty"), 6)
return pro_doc.name return pro_doc
def test_over_production(self): def test_over_production(self):
from erpnext.manufacturing.doctype.production_order.production_order import StockOverProductionError from erpnext.manufacturing.doctype.production_order.production_order import StockOverProductionError
pro_order = self.test_planned_qty() pro_doc = self.test_planned_qty()
stock_entry = make_stock_entry(pro_order, "Manufacture/Repack") s = frappe.get_doc(make_stock_entry(pro_doc.name, "Material Transfer", 7))
stock_entry = frappe.get_doc(stock_entry) for d in s.get("mtn_details"):
stock_entry.posting_date = "2013-05-12" d.s_warehouse = "Stores - _TC"
stock_entry.fiscal_year = "_Test Fiscal Year 2013" s.insert()
stock_entry.fg_completed_qty = 15 s.submit()
stock_entry.set("mtn_details", [])
stock_entry.run_method("get_items")
stock_entry.insert()
self.assertRaises(StockOverProductionError, stock_entry.submit) s = frappe.get_doc(make_stock_entry(pro_doc.name, "Manufacture/Repack", 7))
s.insert()
self.assertRaises(StockOverProductionError, s.submit)
test_records = frappe.get_test_records('Production Order') test_records = frappe.get_test_records('Production Order')

View File

@ -11,13 +11,13 @@ $.extend(erpnext, {
else else
return frappe.boot.sysdefaults.currency; return frappe.boot.sysdefaults.currency;
}, },
hide_naming_series: function() { hide_naming_series: function() {
if(cur_frm.fields_dict.naming_series && !frappe.meta.get_docfield(cur_frm.doctype, "naming_series")) { if(cur_frm.fields_dict.naming_series) {
cur_frm.toggle_display("naming_series", cur_frm.doc.__islocal?true:false); cur_frm.toggle_display("naming_series", cur_frm.doc.__islocal?true:false);
} }
}, },
hide_company: function() { hide_company: function() {
if(cur_frm.fields_dict.company) { if(cur_frm.fields_dict.company) {
var companies = Object.keys(locals[":Company"] || {}); var companies = Object.keys(locals[":Company"] || {});
@ -27,28 +27,28 @@ $.extend(erpnext, {
} }
} }
}, },
add_applicable_territory: function() { add_applicable_territory: function() {
if(cur_frm.doc.__islocal && (cur_frm.doc.valid_for_territories || []).length===0) { if(cur_frm.doc.__islocal && (cur_frm.doc.valid_for_territories || []).length===0) {
var default_territory = frappe.defaults.get_user_default("territory"); var default_territory = frappe.defaults.get_user_default("territory");
if(default_territory) { if(default_territory) {
var territory = frappe.model.add_child(cur_frm.doc, "Applicable Territory", var territory = frappe.model.add_child(cur_frm.doc, "Applicable Territory",
"valid_for_territories"); "valid_for_territories");
territory.territory = default_territory; territory.territory = default_territory;
} }
} }
}, },
setup_serial_no: function(grid_row) { setup_serial_no: function(grid_row) {
if(!grid_row.fields_dict.serial_no || if(!grid_row.fields_dict.serial_no ||
grid_row.fields_dict.serial_no.get_status()!=="Write") return; grid_row.fields_dict.serial_no.get_status()!=="Write") return;
var $btn = $('<button class="btn btn-sm btn-default">'+__("Add Serial No")+'</button>') var $btn = $('<button class="btn btn-sm btn-default">'+__("Add Serial No")+'</button>')
.appendTo($("<div>") .appendTo($("<div>")
.css({"margin-bottom": "10px", "margin-left": "15px"}) .css({"margin-bottom": "10px", "margin-left": "15px"})
.appendTo(grid_row.fields_dict.serial_no.$wrapper)); .appendTo(grid_row.fields_dict.serial_no.$wrapper));
$btn.on("click", function() { $btn.on("click", function() {
var d = new frappe.ui.Dialog({ var d = new frappe.ui.Dialog({
title: __("Add Serial No"), title: __("Add Serial No"),
@ -68,7 +68,7 @@ $.extend(erpnext, {
} }
] ]
}); });
d.get_input("add").on("click", function() { d.get_input("add").on("click", function() {
var serial_no = d.get_value("serial_no"); var serial_no = d.get_value("serial_no");
if(serial_no) { if(serial_no) {
@ -78,8 +78,8 @@ $.extend(erpnext, {
d.hide(); d.hide();
return false; return false;
}); });
d.show(); d.show();
}); });
} }
}); });

View File

@ -162,5 +162,4 @@ def _make_customer(source_name, ignore_permissions=False):
raise raise
except frappe.MandatoryError: except frappe.MandatoryError:
from frappe.utils import get_url_to_form from frappe.utils import get_url_to_form
frappe.throw(_("Before proceeding, please create Customer from Lead") + \ frappe.throw(_("Please create Customer from Lead {0}").format(lead_name))
(" - %s" % get_url_to_form("Lead", lead_name)))

View File

@ -7,7 +7,7 @@ cur_frm.cscript.refresh = function(doc, cdt, cdn) {
if(in_list(user_roles, "System Manager")) if(in_list(user_roles, "System Manager"))
cur_frm.add_custom_button("Replace Abbreviation", cur_frm.cscript.replace_abbr) cur_frm.add_custom_button("Replace Abbreviation", cur_frm.cscript.replace_abbr)
} }
if(!doc.__islocal) { if(!doc.__islocal) {
cur_frm.toggle_enable("default_currency", !cur_frm.doc.__transactions_exist); cur_frm.toggle_enable("default_currency", !cur_frm.doc.__transactions_exist);
} }
@ -60,42 +60,40 @@ cur_frm.cscript.has_special_chars = function(t) {
} }
cur_frm.cscript.company_name = function(doc){ cur_frm.cscript.company_name = function(doc){
if(doc.company_name && cur_frm.cscript.has_special_chars(doc.company_name)){ if(doc.company_name && cur_frm.cscript.has_special_chars(doc.company_name)){
msgprint(("<font color=red>"+__("Special Characters")+" <b>! @ # $ % ^ * + = - [ ] ' ; , / { } | : < > ?</b> "+ msgprint(__("Special Characters not allowed in Company Name"));
__("are not allowed for ")+"</font>\n"+__("Company Name")+" <b> "+ doc.company_name +"</b>")) doc.company_name = '';
doc.company_name = ''; refresh_field('company_name');
refresh_field('company_name'); }
}
} }
cur_frm.cscript.abbr = function(doc){ cur_frm.cscript.abbr = function(doc){
if(doc.abbr && cur_frm.cscript.has_special_chars(doc.abbr)){ if(doc.abbr && cur_frm.cscript.has_special_chars(doc.abbr)){
msgprint("<font color=red>"+__("Special Characters ")+"<b>! @ # $ % ^ * + = - [ ] ' ; , / { } | : < > ?</b>" + msgprint(__("Special Characters not allowed in Abbreviation"));
__("are not allowed for")+ "</font>\nAbbr <b>" + doc.abbr +"</b>") doc.abbr = '';
doc.abbr = ''; refresh_field('abbr');
refresh_field('abbr'); }
}
} }
cur_frm.fields_dict.default_bank_account.get_query = function(doc) { cur_frm.fields_dict.default_bank_account.get_query = function(doc) {
return{ return{
filters: [ filters: [
['Account', 'account_type', 'in', 'Bank, Cash'], ['Account', 'account_type', 'in', 'Bank, Cash'],
['Account', 'group_or_ledger', '=', 'Ledger'], ['Account', 'group_or_ledger', '=', 'Ledger'],
['Account', 'company', '=', doc.name] ['Account', 'company', '=', doc.name]
] ]
} }
} }
cur_frm.fields_dict.default_cash_account.get_query = cur_frm.fields_dict.default_bank_account.get_query; cur_frm.fields_dict.default_cash_account.get_query = cur_frm.fields_dict.default_bank_account.get_query;
cur_frm.fields_dict.receivables_group.get_query = function(doc) { cur_frm.fields_dict.receivables_group.get_query = function(doc) {
return{ return{
filters:{ filters:{
'company': doc.name, 'company': doc.name,
'group_or_ledger': "Group" 'group_or_ledger': "Group"
} }
} }
} }
cur_frm.get_field("chart_of_accounts").get_query = function(doc) { cur_frm.get_field("chart_of_accounts").get_query = function(doc) {
@ -109,33 +107,33 @@ cur_frm.get_field("chart_of_accounts").get_query = function(doc) {
cur_frm.fields_dict.payables_group.get_query = cur_frm.fields_dict.receivables_group.get_query; cur_frm.fields_dict.payables_group.get_query = cur_frm.fields_dict.receivables_group.get_query;
cur_frm.fields_dict.default_expense_account.get_query = function(doc) { cur_frm.fields_dict.default_expense_account.get_query = function(doc) {
return{ return{
filters:{ filters:{
'company': doc.name, 'company': doc.name,
'group_or_ledger': "Ledger", 'group_or_ledger': "Ledger",
"report_type": "Profit and Loss" "report_type": "Profit and Loss"
} }
} }
} }
cur_frm.fields_dict.default_income_account.get_query = function(doc) { cur_frm.fields_dict.default_income_account.get_query = function(doc) {
return{ return{
filters:{ filters:{
'company': doc.name, 'company': doc.name,
'group_or_ledger': "Ledger", 'group_or_ledger': "Ledger",
"report_type": "Profit and Loss" "report_type": "Profit and Loss"
} }
} }
} }
cur_frm.fields_dict.cost_center.get_query = function(doc) { cur_frm.fields_dict.cost_center.get_query = function(doc) {
return{ return{
filters:{ filters:{
'company': doc.name, 'company': doc.name,
'group_or_ledger': "Ledger", 'group_or_ledger': "Ledger",
} }
} }
} }
if (sys_defaults.auto_accounting_for_stock) { if (sys_defaults.auto_accounting_for_stock) {
@ -149,7 +147,7 @@ if (sys_defaults.auto_accounting_for_stock) {
} }
} }
cur_frm.fields_dict["expenses_included_in_valuation"].get_query = cur_frm.fields_dict["expenses_included_in_valuation"].get_query =
cur_frm.fields_dict["stock_adjustment_account"].get_query; cur_frm.fields_dict["stock_adjustment_account"].get_query;
cur_frm.fields_dict["stock_received_but_not_billed"].get_query = function(doc) { cur_frm.fields_dict["stock_received_but_not_billed"].get_query = function(doc) {
@ -161,4 +159,4 @@ if (sys_defaults.auto_accounting_for_stock) {
} }
} }
} }
} }

View File

@ -18,7 +18,7 @@ if(cur_frm.fields_dict['territory']) {
cur_frm.fields_dict['territory'].get_query = function(doc, dt, dn) { cur_frm.fields_dict['territory'].get_query = function(doc, dt, dn) {
return { return {
filters: { filters: {
'is_group': "No" 'is_group': "No"
} }
} }
} }
@ -26,10 +26,10 @@ if(cur_frm.fields_dict['territory']) {
cur_frm.cscript.render_contact_row = function(wrapper, data) { cur_frm.cscript.render_contact_row = function(wrapper, data) {
// prepare data // prepare data
data.fullname = (data.first_name || '') data.fullname = (data.first_name || '')
+ (data.last_name ? ' ' + data.last_name : ''); + (data.last_name ? ' ' + data.last_name : '');
data.primary = data.is_primary_contact ? ' [Primary]' : ''; data.primary = data.is_primary_contact ? ' [Primary]' : '';
// prepare description // prepare description
var description = []; var description = [];
$.each([ $.each([
@ -136,10 +136,7 @@ cur_frm.cscript.render_row_in_wrapper = function(wrapper, data, doctype) {
cur_frm.cscript.delete_doc = function(doctype, name) { cur_frm.cscript.delete_doc = function(doctype, name) {
// confirm deletion // confirm deletion
var go_ahead = confirm(repl('Delete %(doctype)s "%(name)s"', { var go_ahead = confirm(__("Delete {0} {1}?", [doctype, name]));
doctype: doctype,
name: name
}));
if (!go_ahead) return; if (!go_ahead) return;
return frappe.call({ return frappe.call({
@ -183,4 +180,4 @@ cur_frm.cscript.render_list = function(doc, doctype, wrapper, ListView, make_new
cur_frm[doctype.toLowerCase().replace(" ", "_") + "_list"] = record_list_view; cur_frm[doctype.toLowerCase().replace(" ", "_") + "_list"] = record_list_view;
} }
}); });
} }

View File

@ -218,7 +218,7 @@ class Item(WebsiteGenerator):
if merge: if merge:
# Validate properties before merging # Validate properties before merging
if not frappe.db.exists("Item", newdn): if not frappe.db.exists("Item", newdn):
frappe.throw(_("Item ") + newdn +_(" does not exists")) frappe.throw(_("Item {0} does not exist").format(newdn))
field_list = ["stock_uom", "is_stock_item", "has_serial_no", "has_batch_no"] field_list = ["stock_uom", "is_stock_item", "has_serial_no", "has_batch_no"]
new_properties = [cstr(d) for d in frappe.db.get_value("Item", newdn, field_list)] new_properties = [cstr(d) for d in frappe.db.get_value("Item", newdn, field_list)]

View File

@ -27,7 +27,7 @@ class LandedCostWizard(Document):
def validate_purchase_receipts(self, purchase_receipts): def validate_purchase_receipts(self, purchase_receipts):
for pr in purchase_receipts: for pr in purchase_receipts:
if frappe.db.get_value("Purchase Receipt", pr, "docstatus") != 1: if frappe.db.get_value("Purchase Receipt", pr, "docstatus") != 1:
frappe.throw(_("Purchase Receipt") + ": " + pr + _(" is not submitted document")) frappe.throw(_("Purchase Receipt {0} is not submitted").format(pr))
def add_charges_in_pr(self, purchase_receipts): def add_charges_in_pr(self, purchase_receipts):
""" Add additional charges in selected pr proportionately""" """ Add additional charges in selected pr proportionately"""

View File

@ -168,9 +168,8 @@ def update_completed_qty(doc, method):
mr_obj = frappe.get_doc("Material Request", mr_name) mr_obj = frappe.get_doc("Material Request", mr_name)
if mr_obj.status in ["Stopped", "Cancelled"]: if mr_obj.status in ["Stopped", "Cancelled"]:
frappe.throw(_("Material Request") + ": %s, " % mr_obj.name frappe.throw(_("Material Request {0} is cancelled or stopped").format(mr_obj.name),
+ _(mr_obj.meta.get_label("status")) + " = %s. " % _(mr_obj.status) frappe.InvalidStatusError)
+ _("Cannot continue."), exc=frappe.InvalidStatusError)
_update_requested_qty(doc, mr_obj, mr_items) _update_requested_qty(doc, mr_obj, mr_items)

View File

@ -67,7 +67,7 @@ class SerialNo(StockController):
""" """
item = frappe.get_doc("Item", self.item_code) item = frappe.get_doc("Item", self.item_code)
if item.has_serial_no!="Yes": if item.has_serial_no!="Yes":
frappe.throw(_("Item must have 'Has Serial No' as 'Yes'") + ": " + self.item_code) frappe.throw(_("Item {0} is not setup for Serial Nos. Check Item master").format(self.item_code))
self.item_group = item.item_group self.item_group = item.item_group
self.description = item.description self.description = item.description
@ -163,9 +163,9 @@ class SerialNo(StockController):
def on_trash(self): def on_trash(self):
if self.status == 'Delivered': if self.status == 'Delivered':
frappe.throw(_("Delivered Serial No ") + self.name + _(" can not be deleted")) frappe.throw(_("Delivered Serial No {0} cannot be deleted").format(self.name))
if self.warehouse: if self.warehouse:
frappe.throw(_("Cannot delete Serial No in warehouse. First remove from warehouse, then delete.") + ": " + self.name) frappe.throw(_("Cannot delete Serial No {0} in stock. First remove from stock, then delete.").format(self.name))
def before_rename(self, old, new, merge=False): def before_rename(self, old, new, merge=False):
if merge: if merge:
@ -203,51 +203,49 @@ def process_serial_no(sle):
def validate_serial_no(sle, item_det): def validate_serial_no(sle, item_det):
if item_det.has_serial_no=="No": if item_det.has_serial_no=="No":
if sle.serial_no: if sle.serial_no:
frappe.throw(_("Serial Number should be blank for Non Serialized Item" + ": " frappe.throw(_("Item {0} is not setup for Serial Nos. Column must be blank").format(sle.item_code),
+ sle.item_code), SerialNoNotRequiredError) SerialNoNotRequiredError)
else: else:
if sle.serial_no: if sle.serial_no:
serial_nos = get_serial_nos(sle.serial_no) serial_nos = get_serial_nos(sle.serial_no)
if cint(sle.actual_qty) != flt(sle.actual_qty): if cint(sle.actual_qty) != flt(sle.actual_qty):
frappe.throw(_("Serial No qty cannot be a fraction") + \ frappe.throw(_("Serial No {0} quantity {1} cannot be a fraction").format(sle.item_code, sle.actual_qty))
(": %s (%s)" % (sle.item_code, sle.actual_qty)))
if len(serial_nos) and len(serial_nos) != abs(cint(sle.actual_qty)): if len(serial_nos) and len(serial_nos) != abs(cint(sle.actual_qty)):
frappe.throw(_("Serial Nos do not match with qty") + \ frappe.throw(_("{0} Serial Numbers required for Item {0}. Only {0} provided.").format(sle.actual_qty, sle.item_code, len(serial_nos)),
(": %s (%s)" % (sle.item_code, sle.actual_qty)), SerialNoQtyError) SerialNoQtyError)
if len(serial_nos) != len(set(serial_nos)): if len(serial_nos) != len(set(serial_nos)):
frappe.throw(_("Duplicate Serial No entered against item") + frappe.throw(_("Duplicate Serial No entered for Item {0}").format(sle.item_code), SerialNoDuplicateError)
(": %s" % sle.item_code), SerialNoDuplicateError)
for serial_no in serial_nos: for serial_no in serial_nos:
if frappe.db.exists("Serial No", serial_no): if frappe.db.exists("Serial No", serial_no):
sr = frappe.get_doc("Serial No", serial_no) sr = frappe.get_doc("Serial No", serial_no)
if sr.item_code!=sle.item_code: if sr.item_code!=sle.item_code:
frappe.throw(_("Serial No does not belong to Item") + frappe.throw(_("Serial No {0} does not belong to Item {1}").format(sle.item_code,
(": %s (%s)" % (sle.item_code, serial_no)), SerialNoItemError) serial_no), SerialNoItemError)
if sr.warehouse and sle.actual_qty > 0: if sr.warehouse and sle.actual_qty > 0:
frappe.throw(_("Same Serial No") + ": " + sr.name + frappe.throw(_("Serial No {0} has already been received").format(sr.name),
_(" can not be received twice"), SerialNoDuplicateError) SerialNoDuplicateError)
if sle.actual_qty < 0: if sle.actual_qty < 0:
if sr.warehouse!=sle.warehouse: if sr.warehouse!=sle.warehouse:
frappe.throw(_("Serial No") + ": " + serial_no + frappe.throw(_("Serial No {0} does not belong to Warehouse {1}").format(serial_no,
_(" does not belong to Warehouse") + ": " + sle.warehouse, sle.warehouse), SerialNoWarehouseError)
SerialNoWarehouseError)
if sle.voucher_type in ("Delivery Note", "Sales Invoice") \ if sle.voucher_type in ("Delivery Note", "Sales Invoice") \
and sr.status != "Available": and sr.status != "Available":
frappe.throw(_("Serial No status must be 'Available' to Deliver") frappe.throw(_("Serial No {0} status must be 'Available' to Deliver").format(serial_no),
+ ": " + serial_no, SerialNoStatusError) SerialNoStatusError)
elif sle.actual_qty < 0: elif sle.actual_qty < 0:
# transfer out # transfer out
frappe.throw(_("Serial No must exist to transfer out.") + \ frappe.throw(_("Serial No {0} not in stock").format(serial_no), SerialNoNotExistsError)
": " + serial_no, SerialNoNotExistsError)
elif sle.actual_qty < 0 or not item_det.serial_no_series: elif sle.actual_qty < 0 or not item_det.serial_no_series:
frappe.throw(_("Serial Number Required for Serialized Item" + ": " frappe.throw(_("Serial Nos Required for Serialized Item {0}").format(sle.item_code),
+ sle.item_code), SerialNoRequiredError) SerialNoRequiredError)
def update_serial_nos(sle, item_det): def update_serial_nos(sle, item_det):
if sle.is_cancelled == "No" and not sle.serial_no and sle.actual_qty > 0 and item_det.serial_no_series: if sle.is_cancelled == "No" and not sle.serial_no and sle.actual_qty > 0 and item_det.serial_no_series:

View File

@ -10,22 +10,22 @@ frappe.provide("erpnext.stock");
erpnext.stock.StockEntry = erpnext.stock.StockController.extend({ erpnext.stock.StockEntry = erpnext.stock.StockController.extend({
setup: function() { setup: function() {
var me = this; var me = this;
this.frm.fields_dict.delivery_note_no.get_query = function() { this.frm.fields_dict.delivery_note_no.get_query = function() {
return { query: "erpnext.stock.doctype.stock_entry.stock_entry.query_sales_return_doc" }; return { query: "erpnext.stock.doctype.stock_entry.stock_entry.query_sales_return_doc" };
}; };
this.frm.fields_dict.sales_invoice_no.get_query = this.frm.fields_dict.sales_invoice_no.get_query =
this.frm.fields_dict.delivery_note_no.get_query; this.frm.fields_dict.delivery_note_no.get_query;
this.frm.fields_dict.purchase_receipt_no.get_query = function() { this.frm.fields_dict.purchase_receipt_no.get_query = function() {
return { return {
filters:{ 'docstatus': 1 } filters:{ 'docstatus': 1 }
}; };
}; };
this.frm.fields_dict.mtn_details.grid.get_field('item_code').get_query = function() { this.frm.fields_dict.mtn_details.grid.get_field('item_code').get_query = function() {
if(in_list(["Sales Return", "Purchase Return"], me.frm.doc.purpose) && if(in_list(["Sales Return", "Purchase Return"], me.frm.doc.purpose) &&
me.get_doctype_docname()) { me.get_doctype_docname()) {
return { return {
query: "erpnext.stock.doctype.stock_entry.stock_entry.query_return_item", query: "erpnext.stock.doctype.stock_entry.stock_entry.query_return_item",
@ -40,13 +40,13 @@ erpnext.stock.StockEntry = erpnext.stock.StockController.extend({
return erpnext.queries.item({is_stock_item: "Yes"}); return erpnext.queries.item({is_stock_item: "Yes"});
} }
}; };
if(cint(frappe.defaults.get_default("auto_accounting_for_stock"))) { if(cint(frappe.defaults.get_default("auto_accounting_for_stock"))) {
this.frm.add_fetch("company", "stock_adjustment_account", "expense_account"); this.frm.add_fetch("company", "stock_adjustment_account", "expense_account");
this.frm.fields_dict.mtn_details.grid.get_field('expense_account').get_query = this.frm.fields_dict.mtn_details.grid.get_field('expense_account').get_query =
function() { function() {
return { return {
filters: { filters: {
"company": me.frm.doc.company, "company": me.frm.doc.company,
"group_or_ledger": "Ledger" "group_or_ledger": "Ledger"
} }
@ -66,8 +66,8 @@ erpnext.stock.StockEntry = erpnext.stock.StockController.extend({
this.toggle_enable_bom(); this.toggle_enable_bom();
this.show_stock_ledger(); this.show_stock_ledger();
this.show_general_ledger(); this.show_general_ledger();
if(this.frm.doc.docstatus === 1 && if(this.frm.doc.docstatus === 1 &&
frappe.boot.user.can_create.indexOf("Journal Voucher")!==-1) { frappe.boot.user.can_create.indexOf("Journal Voucher")!==-1) {
if(this.frm.doc.purpose === "Sales Return") { if(this.frm.doc.purpose === "Sales Return") {
this.frm.add_custom_button(__("Make Credit Note"), function() { me.make_return_jv(); }); this.frm.add_custom_button(__("Make Credit Note"), function() { me.make_return_jv(); });
@ -77,7 +77,7 @@ erpnext.stock.StockEntry = erpnext.stock.StockController.extend({
this.add_excise_button(); this.add_excise_button();
} }
} }
}, },
on_submit: function() { on_submit: function() {
@ -90,22 +90,22 @@ erpnext.stock.StockEntry = erpnext.stock.StockController.extend({
set_default_account: function() { set_default_account: function() {
var me = this; var me = this;
if(cint(frappe.defaults.get_default("auto_accounting_for_stock"))) { if(cint(frappe.defaults.get_default("auto_accounting_for_stock"))) {
var account_for = "stock_adjustment_account"; var account_for = "stock_adjustment_account";
if (this.frm.doc.purpose == "Purchase Return") if (this.frm.doc.purpose == "Purchase Return")
account_for = "stock_received_but_not_billed"; account_for = "stock_received_but_not_billed";
return this.frm.call({ return this.frm.call({
method: "erpnext.accounts.utils.get_company_default", method: "erpnext.accounts.utils.get_company_default",
args: { args: {
"fieldname": account_for, "fieldname": account_for,
"company": this.frm.doc.company "company": this.frm.doc.company
}, },
callback: function(r) { callback: function(r) {
if (!r.exc) { if (!r.exc) {
$.each(doc.mtn_details || [], function(i, d) { $.each(me.frm.doc.mtn_details || [], function(i, d) {
if(!d.expense_account) d.expense_account = r.message; if(!d.expense_account) d.expense_account = r.message;
}); });
} }
@ -116,9 +116,9 @@ erpnext.stock.StockEntry = erpnext.stock.StockController.extend({
clean_up: function() { clean_up: function() {
// Clear Production Order record from locals, because it is updated via Stock Entry // Clear Production Order record from locals, because it is updated via Stock Entry
if(this.frm.doc.production_order && if(this.frm.doc.production_order &&
this.frm.doc.purpose == "Manufacture/Repack") { this.frm.doc.purpose == "Manufacture/Repack") {
frappe.model.remove_from_locals("Production Order", frappe.model.remove_from_locals("Production Order",
this.frm.doc.production_order); this.frm.doc.production_order);
} }
}, },
@ -145,7 +145,7 @@ erpnext.stock.StockEntry = erpnext.stock.StockController.extend({
production_order: function() { production_order: function() {
var me = this; var me = this;
this.toggle_enable_bom(); this.toggle_enable_bom();
return this.frm.call({ return this.frm.call({
method: "get_production_order_details", method: "get_production_order_details",
args: {production_order: this.frm.doc.production_order}, args: {production_order: this.frm.doc.production_order},
@ -167,26 +167,26 @@ erpnext.stock.StockEntry = erpnext.stock.StockController.extend({
if(this.frm.doc.delivery_note_no && this.frm.doc.sales_invoice_no) { if(this.frm.doc.delivery_note_no && this.frm.doc.sales_invoice_no) {
// both specified // both specified
msgprint(__("You can not enter both Delivery Note No and Sales Invoice No. Please enter any one.")); msgprint(__("You can not enter both Delivery Note No and Sales Invoice No. Please enter any one."));
} else if(!(this.frm.doc.delivery_note_no || this.frm.doc.sales_invoice_no)) { } else if(!(this.frm.doc.delivery_note_no || this.frm.doc.sales_invoice_no)) {
// none specified // none specified
msgprint(__("Please enter Delivery Note No or Sales Invoice No to proceed")); msgprint(__("Please enter Delivery Note No or Sales Invoice No to proceed"));
} else if(this.frm.doc.delivery_note_no) { } else if(this.frm.doc.delivery_note_no) {
return {doctype: "Delivery Note", docname: this.frm.doc.delivery_note_no}; return {doctype: "Delivery Note", docname: this.frm.doc.delivery_note_no};
} else if(this.frm.doc.sales_invoice_no) { } else if(this.frm.doc.sales_invoice_no) {
return {doctype: "Sales Invoice", docname: this.frm.doc.sales_invoice_no}; return {doctype: "Sales Invoice", docname: this.frm.doc.sales_invoice_no};
} }
} else if(this.frm.doc.purpose === "Purchase Return") { } else if(this.frm.doc.purpose === "Purchase Return") {
if(this.frm.doc.purchase_receipt_no) { if(this.frm.doc.purchase_receipt_no) {
return {doctype: "Purchase Receipt", docname: this.frm.doc.purchase_receipt_no}; return {doctype: "Purchase Receipt", docname: this.frm.doc.purchase_receipt_no};
} else { } else {
// not specified // not specified
msgprint(__("Please enter Purchase Receipt No to proceed")); msgprint(__("Please enter Purchase Receipt No to proceed"));
} }
} }
}, },
@ -226,9 +226,9 @@ erpnext.stock.StockEntry = erpnext.stock.StockController.extend({
mtn_details_add: function(doc, cdt, cdn) { mtn_details_add: function(doc, cdt, cdn) {
var row = frappe.get_doc(cdt, cdn); var row = frappe.get_doc(cdt, cdn);
this.frm.script_manager.copy_from_first_row("mtn_details", row, this.frm.script_manager.copy_from_first_row("mtn_details", row,
["expense_account", "cost_center"]); ["expense_account", "cost_center"]);
if(!row.s_warehouse) row.s_warehouse = this.frm.doc.from_warehouse; if(!row.s_warehouse) row.s_warehouse = this.frm.doc.from_warehouse;
if(!row.t_warehouse) row.t_warehouse = this.frm.doc.to_warehouse; if(!row.t_warehouse) row.t_warehouse = this.frm.doc.to_warehouse;
}, },
@ -236,49 +236,49 @@ erpnext.stock.StockEntry = erpnext.stock.StockController.extend({
mtn_details_on_form_rendered: function(doc, grid_row) { mtn_details_on_form_rendered: function(doc, grid_row) {
erpnext.setup_serial_no(grid_row) erpnext.setup_serial_no(grid_row)
}, },
customer: function() { customer: function() {
return this.frm.call({ return this.frm.call({
method: "erpnext.accounts.party.get_party_details", method: "erpnext.accounts.party.get_party_details",
args: { party: this.frm.doc.customer, party_type:"Customer" } args: { party: this.frm.doc.customer, party_type:"Customer" }
}); });
}, },
supplier: function() { supplier: function() {
return this.frm.call({ return this.frm.call({
method: "erpnext.accounts.party.get_party_details", method: "erpnext.accounts.party.get_party_details",
args: { party: this.frm.doc.supplier, party_type:"Supplier" } args: { party: this.frm.doc.supplier, party_type:"Supplier" }
}); });
}, },
delivery_note_no: function() { delivery_note_no: function() {
this.get_party_details({ this.get_party_details({
ref_dt: "Delivery Note", ref_dt: "Delivery Note",
ref_dn: this.frm.doc.delivery_note_no ref_dn: this.frm.doc.delivery_note_no
}) })
}, },
sales_invoice_no: function() { sales_invoice_no: function() {
this.get_party_details({ this.get_party_details({
ref_dt: "Sales Invoice", ref_dt: "Sales Invoice",
ref_dn: this.frm.doc.sales_invoice_no ref_dn: this.frm.doc.sales_invoice_no
}) })
}, },
purchase_receipt_no: function() { purchase_receipt_no: function() {
this.get_party_details({ this.get_party_details({
ref_dt: "Purchase Receipt", ref_dt: "Purchase Receipt",
ref_dn: this.frm.doc.purchase_receipt_no ref_dn: this.frm.doc.purchase_receipt_no
}) })
}, },
get_party_details: function(args) { get_party_details: function(args) {
return this.frm.call({ return this.frm.call({
method: "erpnext.stock.doctype.stock_entry.stock_entry.get_party_details", method: "erpnext.stock.doctype.stock_entry.stock_entry.get_party_details",
args: args, args: args,
}) })
} }
}); });
cur_frm.script_manager.make(erpnext.stock.StockEntry); cur_frm.script_manager.make(erpnext.stock.StockEntry);
@ -286,23 +286,23 @@ cur_frm.script_manager.make(erpnext.stock.StockEntry);
cur_frm.cscript.toggle_related_fields = function(doc) { cur_frm.cscript.toggle_related_fields = function(doc) {
disable_from_warehouse = inList(["Material Receipt", "Sales Return"], doc.purpose); disable_from_warehouse = inList(["Material Receipt", "Sales Return"], doc.purpose);
disable_to_warehouse = inList(["Material Issue", "Purchase Return"], doc.purpose); disable_to_warehouse = inList(["Material Issue", "Purchase Return"], doc.purpose);
cur_frm.toggle_enable("from_warehouse", !disable_from_warehouse); cur_frm.toggle_enable("from_warehouse", !disable_from_warehouse);
cur_frm.toggle_enable("to_warehouse", !disable_to_warehouse); cur_frm.toggle_enable("to_warehouse", !disable_to_warehouse);
cur_frm.fields_dict["mtn_details"].grid.set_column_disp("s_warehouse", !disable_from_warehouse); cur_frm.fields_dict["mtn_details"].grid.set_column_disp("s_warehouse", !disable_from_warehouse);
cur_frm.fields_dict["mtn_details"].grid.set_column_disp("t_warehouse", !disable_to_warehouse); cur_frm.fields_dict["mtn_details"].grid.set_column_disp("t_warehouse", !disable_to_warehouse);
if(doc.purpose == 'Purchase Return') { if(doc.purpose == 'Purchase Return') {
doc.customer = doc.customer_name = doc.customer_address = doc.customer = doc.customer_name = doc.customer_address =
doc.delivery_note_no = doc.sales_invoice_no = null; doc.delivery_note_no = doc.sales_invoice_no = null;
doc.bom_no = doc.production_order = doc.fg_completed_qty = null; doc.bom_no = doc.production_order = doc.fg_completed_qty = null;
} else if(doc.purpose == 'Sales Return') { } else if(doc.purpose == 'Sales Return') {
doc.supplier=doc.supplier_name = doc.supplier_address = doc.purchase_receipt_no=null; doc.supplier=doc.supplier_name = doc.supplier_address = doc.purchase_receipt_no=null;
doc.bom_no = doc.production_order = doc.fg_completed_qty = null; doc.bom_no = doc.production_order = doc.fg_completed_qty = null;
} else { } else {
doc.customer = doc.customer_name = doc.customer_address = doc.customer = doc.customer_name = doc.customer_address =
doc.delivery_note_no = doc.sales_invoice_no = doc.supplier = doc.delivery_note_no = doc.sales_invoice_no = doc.supplier =
doc.supplier_name = doc.supplier_address = doc.purchase_receipt_no = null; doc.supplier_name = doc.supplier_address = doc.purchase_receipt_no = null;
} }
} }
@ -331,7 +331,7 @@ cur_frm.fields_dict['mtn_details'].grid.get_field('batch_no').get_query = functi
's_warehouse': d.s_warehouse, 's_warehouse': d.s_warehouse,
'posting_date': doc.posting_date 'posting_date': doc.posting_date
} }
} }
} else { } else {
msgprint(__("Please enter Item Code to get batch no")); msgprint(__("Please enter Item Code to get batch no"));
} }
@ -350,10 +350,10 @@ cur_frm.cscript.item_code = function(doc, cdt, cdn) {
'cost_center' : d.cost_center, 'cost_center' : d.cost_center,
'company' : cur_frm.doc.company 'company' : cur_frm.doc.company
}; };
return get_server_fields('get_item_details', {arg: JSON.stringify(args)}, return get_server_fields('get_item_details', {arg: JSON.stringify(args)},
'mtn_details', doc, cdt, cdn, 1); 'mtn_details', doc, cdt, cdn, 1);
} }
} }
cur_frm.cscript.s_warehouse = function(doc, cdt, cdn) { cur_frm.cscript.s_warehouse = function(doc, cdt, cdn) {
@ -366,7 +366,7 @@ cur_frm.cscript.s_warehouse = function(doc, cdt, cdn) {
'bom_no' : d.bom_no, 'bom_no' : d.bom_no,
'qty' : d.s_warehouse ? -1* d.qty : d.qty 'qty' : d.s_warehouse ? -1* d.qty : d.qty
} }
return get_server_fields('get_warehouse_details', JSON.stringify(args), return get_server_fields('get_warehouse_details', JSON.stringify(args),
'mtn_details', doc, cdt, cdn, 1); 'mtn_details', doc, cdt, cdn, 1);
} }
@ -376,7 +376,7 @@ cur_frm.cscript.uom = function(doc, cdt, cdn) {
var d = locals[cdt][cdn]; var d = locals[cdt][cdn];
if(d.uom && d.item_code){ if(d.uom && d.item_code){
var arg = {'item_code':d.item_code, 'uom':d.uom, 'qty':d.qty} var arg = {'item_code':d.item_code, 'uom':d.uom, 'qty':d.qty}
return get_server_fields('get_uom_details', JSON.stringify(arg), return get_server_fields('get_uom_details', JSON.stringify(arg),
'mtn_details', doc, cdt, cdn, 1); 'mtn_details', doc, cdt, cdn, 1);
} }
} }

View File

@ -72,7 +72,15 @@ class StockEntry(StockController):
stock_items = self.get_stock_items() stock_items = self.get_stock_items()
for item in self.get("mtn_details"): for item in self.get("mtn_details"):
if item.item_code not in stock_items: if item.item_code not in stock_items:
frappe.throw(_("""Only Stock Items are allowed for Stock Entry""")) frappe.throw(_("{0} is not a stock Item").format(item.item_code))
if not item.stock_uom:
item.stock_uom = frappe.db.get_value("Item", item.item_code, "stock_uom")
if not item.uom:
item.uom = item.stock_uom
if not item.conversion_factor:
item.conversion_factor = 1
if not item.transfer_qty:
item.transfer_qty = item.qty * item.conversion_factor
def validate_warehouse(self, pro_obj): def validate_warehouse(self, pro_obj):
"""perform various (sometimes conditional) validations on warehouse""" """perform various (sometimes conditional) validations on warehouse"""
@ -224,7 +232,7 @@ class StockEntry(StockController):
"""validation: finished good quantity should be same as manufacturing quantity""" """validation: finished good quantity should be same as manufacturing quantity"""
for d in self.get('mtn_details'): for d in self.get('mtn_details'):
if d.bom_no and flt(d.transfer_qty) != flt(self.fg_completed_qty): if d.bom_no and flt(d.transfer_qty) != flt(self.fg_completed_qty):
frappe.throw(_("Quantity in row {0} must be same as manufactured quantity").format(d.idx)) frappe.throw(_("Quantity in row {0} ({1}) must be same as manufactured quantity {2}").format(d.idx, d.transfer_qty, self.fg_completed_qty))
def validate_return_reference_doc(self): def validate_return_reference_doc(self):
"""validate item with reference doc""" """validate item with reference doc"""

View File

@ -47,7 +47,7 @@ class StockLedgerEntry(DocListController):
mandatory = ['warehouse','posting_date','voucher_type','voucher_no','actual_qty','company'] mandatory = ['warehouse','posting_date','voucher_type','voucher_no','actual_qty','company']
for k in mandatory: for k in mandatory:
if not self.get(k): if not self.get(k):
frappe.throw(_("{0} is required").format(k)) frappe.throw(_("{0} is required").format(self.meta.get_label(k)))
def validate_item(self): def validate_item(self):
item_det = frappe.db.sql("""select name, has_batch_no, docstatus, item_det = frappe.db.sql("""select name, has_batch_no, docstatus,

View File

@ -138,9 +138,7 @@ class StockReconciliation(StockController):
# check valuation rate mandatory # check valuation rate mandatory
if row.qty != "" and not row.valuation_rate and \ if row.qty != "" and not row.valuation_rate and \
flt(previous_sle.get("qty_after_transaction")) <= 0: flt(previous_sle.get("qty_after_transaction")) <= 0:
frappe.throw(_("As existing qty for item: ") + row.item_code + frappe.throw(_("Valuation Rate required for Item {0}").format(row.item_code))
_(" at warehouse: ") + row.warehouse +
_(" is less than equals to zero in the system, valuation rate is mandatory for this item"))
change_in_qty = row.qty != "" and \ change_in_qty = row.qty != "" and \
(flt(row.qty) - flt(previous_sle.get("qty_after_transaction"))) (flt(row.qty) - flt(previous_sle.get("qty_after_transaction")))

View File

@ -94,7 +94,7 @@ class Warehouse(Document):
if merge: if merge:
if not frappe.db.exists("Warehouse", new_warehouse): if not frappe.db.exists("Warehouse", new_warehouse):
frappe.throw(_("Warehouse ") + new_warehouse +_(" does not exists")) frappe.throw(_("Warehouse {0} does not exist").format(new_warehouse))
if self.company != frappe.db.get_value("Warehouse", new_warehouse, "company"): if self.company != frappe.db.get_value("Warehouse", new_warehouse, "company"):
frappe.throw(_("Both Warehouse must belong to same Company")) frappe.throw(_("Both Warehouse must belong to same Company"))

View File

@ -79,12 +79,12 @@ def get_item_details(args):
def get_item_code(barcode=None, serial_no=None): def get_item_code(barcode=None, serial_no=None):
if barcode: if barcode:
item_code = frappe.db.get_value("Item", {"barcode": barcode}) item_code = frappe.db.get_value("Item", {"barcode": barcode})
if not item_code:
frappe.throw(_("No Item with Barcode {0}").format(barcode))
elif serial_no: elif serial_no:
item_code = frappe.db.get_value("Serial No", serial_no, "item_code") item_code = frappe.db.get_value("Serial No", serial_no, "item_code")
if not item_code:
if not item_code: frappe.throw(_("No Item with Serial No {0}").format(serial_no))
throw(_("No Item found with ") + _("Barcode") if barcode else _("Serial No") +
": %s" % (barcode or serial_no))
return item_code return item_code
@ -99,22 +99,18 @@ def validate_item_details(args, item):
# validate if sales item or service item # validate if sales item or service item
if args.get("order_type") == "Maintenance": if args.get("order_type") == "Maintenance":
if item.is_service_item != "Yes": if item.is_service_item != "Yes":
throw(_("Item") + (" %s: " % item.name) + throw(_("Item {0} must be a Service Item.").format(item.name))
_("is not a service item.") +
_("Please select a service item or change the order type to Sales."))
elif item.is_sales_item != "Yes": elif item.is_sales_item != "Yes":
throw(_("Item") + (" %s: " % item.name) + _("is not a sales item")) throw(_("Item {0} must be a Sales Item").format(item.name))
elif args.transaction_type == "buying": elif args.transaction_type == "buying":
# validate if purchase item or subcontracted item # validate if purchase item or subcontracted item
if item.is_purchase_item != "Yes": if item.is_purchase_item != "Yes":
throw(_("Item") + (" %s: " % item.name) + _("is not a purchase item")) throw(_("Item {0} must be a Purchase Item").format(item.name))
if args.get("is_subcontracted") == "Yes" and item.is_sub_contracted_item != "Yes": if args.get("is_subcontracted") == "Yes" and item.is_sub_contracted_item != "Yes":
throw(_("Item") + (" %s: " % item.name) + throw(_("Item {0} must be a Sub-contracted Item").format(item.name))
_("not a sub-contracted item.") +
_("Please select a sub-contracted item or do not sub-contract the transaction."))
def get_basic_details(args, item_doc): def get_basic_details(args, item_doc):
item = item_doc item = item_doc
@ -180,7 +176,7 @@ def validate_price_list(args):
if args.get("price_list"): if args.get("price_list"):
if not frappe.db.get_value("Price List", if not frappe.db.get_value("Price List",
{"name": args.price_list, args.transaction_type: 1, "enabled": 1}): {"name": args.price_list, args.transaction_type: 1, "enabled": 1}):
throw(_("Price List is either disabled or for not ") + _(args.transaction_type)) throw(_("Price List {0} is disabled").format(args.price_list))
else: else:
throw(_("Price List not selected")) throw(_("Price List not selected"))

View File

@ -176,14 +176,14 @@ class MaintenanceSchedule(TransactionBase):
if not d.item_code: if not d.item_code:
throw(_("Please select item code")) throw(_("Please select item code"))
elif not d.start_date or not d.end_date: elif not d.start_date or not d.end_date:
throw(_("Please select Start Date and End Date for item") + " " + d.item_code) throw(_("Please select Start Date and End Date for Item {0}".format(d.item_code)))
elif not d.no_of_visits: elif not d.no_of_visits:
throw(_("Please mention no of visits required")) throw(_("Please mention no of visits required"))
elif not d.sales_person: elif not d.sales_person:
throw(_("Please select Incharge Person's name")) throw(_("Please select Incharge Person's name"))
if getdate(d.start_date) >= getdate(d.end_date): if getdate(d.start_date) >= getdate(d.end_date):
throw(_("Start date should be less than end date for item") + " " + d.item_code) throw(_("Start date should be less than end date for Item {0}").format(d.item_code))
def validate_sales_order(self): def validate_sales_order(self):
for d in self.get('item_maintenance_detail'): for d in self.get('item_maintenance_detail'):
@ -238,8 +238,7 @@ class MaintenanceSchedule(TransactionBase):
else: else:
for x in item_lst1: for x in item_lst1:
if x not in item_lst2: if x not in item_lst2:
throw(_("Maintenance Schedule is not generated for item ") + x + throw(_("Please click on 'Generate Schedule'"))
_(". Please click on 'Generate Schedule'"))
def check_serial_no_added(self): def check_serial_no_added(self):
serial_present =[] serial_present =[]

File diff suppressed because it is too large Load Diff