Merge branch 'edge' of github.com:webnotes/erpnext into webshop

Conflicts:
	patches/april_2013/p05_update_file_data.py
This commit is contained in:
Anand Doshi 2013-05-01 14:48:16 +05:30
commit 447008b045
38 changed files with 723 additions and 169 deletions

View File

@ -81,7 +81,7 @@ class DocType(DocTypeNestedSet):
""" """
Cost Center name must be unique Cost Center name must be unique
""" """
if (self.doc.__islocal or not self.doc.name) and webnotes.conn.sql("select name from `tabCost Center` where cost_center_name = %s and company_name=%s", (self.doc.cost_center_name, self.doc.company_name)): if (self.doc.fields.get("__islocal") or not self.doc.name) and webnotes.conn.sql("select name from `tabCost Center` where cost_center_name = %s and company_name=%s", (self.doc.cost_center_name, self.doc.company_name)):
msgprint("Cost Center Name already exists, please rename", raise_exception=1) msgprint("Cost Center Name already exists, please rename", raise_exception=1)
self.validate_mandatory() self.validate_mandatory()

View File

@ -108,8 +108,8 @@ class DocType:
and not 'Accounts Manager' in webnotes.user.get_roles(): and not 'Accounts Manager' in webnotes.user.get_roles():
msgprint(_("Account") + ": " + self.doc.account + _(" has been freezed. \ msgprint(_("Account") + ": " + self.doc.account + _(" has been freezed. \
Only Accounts Manager can do transaction against this account"), raise_exception=1) Only Accounts Manager can do transaction against this account"), raise_exception=1)
if ret and ret[0]["company"] != self.doc.company: if self.doc.is_cancelled in ("No", None) and ret and ret[0]["company"] != self.doc.company:
msgprint(_("Account") + ": " + self.doc.account + _(" does not belong to the company") \ msgprint(_("Account") + ": " + self.doc.account + _(" does not belong to the company") \
+ ": " + self.doc.company, raise_exception=1) + ": " + self.doc.company, raise_exception=1)
@ -124,9 +124,10 @@ class DocType:
return self.cost_center_company[self.doc.cost_center] return self.cost_center_company[self.doc.cost_center]
if self.doc.cost_center and _get_cost_center_company() != self.doc.company: if self.doc.is_cancelled in ("No", None) and \
msgprint(_("Cost Center") + ": " + self.doc.cost_center \ self.doc.cost_center and _get_cost_center_company() != self.doc.company:
+ _(" does not belong to the company") + ": " + self.doc.company, raise_exception=True) msgprint(_("Cost Center") + ": " + self.doc.cost_center \
+ _(" does not belong to the company") + ": " + self.doc.company, raise_exception=True)
def check_freezing_date(self, adv_adj): def check_freezing_date(self, adv_adj):
""" """

View File

@ -72,7 +72,38 @@ class TestPurchaseInvoice(unittest.TestCase):
["Stock Received But Not Billed - _TC", 750.0, 0], ["Stock Received But Not Billed - _TC", 750.0, 0],
["_Test Account Shipping Charges - _TC", 100.0, 0], ["_Test Account Shipping Charges - _TC", 100.0, 0],
["_Test Account VAT - _TC", 120.0, 0], ["_Test Account VAT - _TC", 120.0, 0],
["Expenses Included In Valuation - _TC", 0, 250.0] ["Expenses Included In Valuation - _TC", 0, 250.0],
])
for i, gle in enumerate(gl_entries):
self.assertEquals(expected_values[i][0], gle.account)
self.assertEquals(expected_values[i][1], gle.debit)
self.assertEquals(expected_values[i][2], gle.credit)
webnotes.defaults.set_global_default("auto_inventory_accounting", 0)
def test_gl_entries_with_aia_for_non_stock_items(self):
webnotes.defaults.set_global_default("auto_inventory_accounting", 1)
self.assertEqual(cint(webnotes.defaults.get_global_default("auto_inventory_accounting")), 1)
pi = webnotes.bean(copy=test_records[1])
pi.doclist[1].item_code = "_Test Non Stock Item"
pi.doclist[1].expense_head = "_Test Account Cost for Goods Sold - _TC"
pi.doclist.pop(2)
pi.doclist.pop(3)
pi.run_method("calculate_taxes_and_totals")
pi.insert()
pi.submit()
gl_entries = webnotes.conn.sql("""select account, debit, credit
from `tabGL Entry` where voucher_type='Purchase Invoice' and voucher_no=%s
order by account asc""", pi.doc.name, as_dict=1)
self.assertTrue(gl_entries)
expected_values = sorted([
["_Test Supplier - _TC", 0, 620],
["_Test Account Cost for Goods Sold - _TC", 500.0, 0],
["_Test Account VAT - _TC", 120.0, 0],
]) ])
for i, gle in enumerate(gl_entries): for i, gle in enumerate(gl_entries):
@ -106,7 +137,6 @@ class TestPurchaseInvoice(unittest.TestCase):
self.assertEqual(tax.account_head, expected_values[i][0]) self.assertEqual(tax.account_head, expected_values[i][0])
self.assertEqual(tax.tax_amount, expected_values[i][1]) self.assertEqual(tax.tax_amount, expected_values[i][1])
self.assertEqual(tax.total, expected_values[i][2]) self.assertEqual(tax.total, expected_values[i][2])
# print tax.account_head, tax.tax_amount, tax.item_wise_tax_detail
expected_values = [ expected_values = [
["_Test Item Home Desktop 100", 90, 59], ["_Test Item Home Desktop 100", 90, 59],
@ -142,7 +172,6 @@ class TestPurchaseInvoice(unittest.TestCase):
self.assertEqual(tax.account_head, expected_values[i][0]) self.assertEqual(tax.account_head, expected_values[i][0])
self.assertEqual(tax.tax_amount, expected_values[i][1]) self.assertEqual(tax.tax_amount, expected_values[i][1])
self.assertEqual(tax.total, expected_values[i][2]) self.assertEqual(tax.total, expected_values[i][2])
# print tax.account_head, tax.tax_amount, tax.item_wise_tax_detail
expected_values = [ expected_values = [
["_Test FG Item", 90, 7059], ["_Test FG Item", 90, 7059],

View File

@ -149,6 +149,16 @@ wn.module_page["Accounts"] = [
route: "query-report/Accounts Payable", route: "query-report/Accounts Payable",
doctype: "Purchase Invoice" doctype: "Purchase Invoice"
}, },
{
"label":wn._("Sales Register"),
route: "query-report/Sales Register",
doctype: "Sales Invoice"
},
{
"label":wn._("Purchase Register"),
route: "query-report/Purchase Register",
doctype: "Purchase Invoice"
},
] ]
}, },
{ {

View File

@ -186,7 +186,6 @@ erpnext.GeneralLedger = wn.views.GridReport.extend({
var totals = this.make_summary_row("Totals", this.account); var totals = this.make_summary_row("Totals", this.account);
var grouped_ledgers = {}; var grouped_ledgers = {};
$.each(data, function(i, item) { $.each(data, function(i, item) {
if((me.is_default("company") ? true : me.apply_filter(item, "company")) && if((me.is_default("company") ? true : me.apply_filter(item, "company")) &&
(me.account ? me.is_child_account(me.account, item.account) (me.account ? me.is_child_account(me.account, item.account)
@ -217,8 +216,7 @@ erpnext.GeneralLedger = wn.views.GridReport.extend({
grouped_ledgers[item.account].totals.debit += item.debit; grouped_ledgers[item.account].totals.debit += item.debit;
grouped_ledgers[item.account].totals.credit += item.credit; grouped_ledgers[item.account].totals.credit += item.credit;
} }
if(item.account) {
if(me.account) {
item.against_account = me.voucher_accounts[item.voucher_type + ":" item.against_account = me.voucher_accounts[item.voucher_type + ":"
+ item.voucher_no][(item.debit > 0 ? "credits" : "debits")].join(", "); + item.voucher_no][(item.debit > 0 ? "credits" : "debits")].join(", ");
} }

View File

@ -19,7 +19,6 @@ def execute(filters=None):
and nowdate() or filters.get("report_date") and nowdate() or filters.get("report_date")
data = [] data = []
total_invoiced_amount = total_paid = total_outstanding = 0
for gle in entries: for gle in entries:
if cstr(gle.against_voucher) == gle.voucher_no or not gle.against_voucher \ if cstr(gle.against_voucher) == gle.voucher_no or not gle.against_voucher \
or [gle.against_voucher_type, gle.against_voucher] in entries_after_report_date: or [gle.against_voucher_type, gle.against_voucher] in entries_after_report_date:
@ -36,7 +35,7 @@ def execute(filters=None):
paid_amount = get_paid_amount(gle, filters.get("report_date") or nowdate(), paid_amount = get_paid_amount(gle, filters.get("report_date") or nowdate(),
entries_after_report_date) entries_after_report_date)
outstanding_amount = invoiced_amount - paid_amount outstanding_amount = invoiced_amount - paid_amount
if abs(flt(outstanding_amount)) > 0.01: if abs(flt(outstanding_amount)) > 0.01:
row = [gle.posting_date, gle.account, gle.voucher_type, gle.voucher_no, row = [gle.posting_date, gle.account, gle.voucher_type, gle.voucher_no,
gle.remarks, account_supplier_type_map.get(gle.account), due_date, bill_no, gle.remarks, account_supplier_type_map.get(gle.account), due_date, bill_no,
@ -47,16 +46,9 @@ def execute(filters=None):
ageing_based_on_date = due_date ageing_based_on_date = due_date
else: else:
ageing_based_on_date = gle.posting_date ageing_based_on_date = gle.posting_date
row += get_ageing_data(ageing_based_on_date, age_on, outstanding_amount) row += get_ageing_data(ageing_based_on_date, age_on, outstanding_amount)
# Add to total
total_invoiced_amount += flt(invoiced_amount)
total_paid += flt(paid_amount)
total_outstanding += flt(outstanding_amount)
data.append(row) data.append(row)
if data:
data.append(["", "", "", "", "", "", "", "Total", "", total_invoiced_amount, total_paid,
total_outstanding, "", "", "", ""])
return columns, data return columns, data

View File

@ -2,11 +2,12 @@
{ {
"creation": "2013-04-22 16:16:03", "creation": "2013-04-22 16:16:03",
"docstatus": 0, "docstatus": 0,
"modified": "2013-04-23 14:54:27", "modified": "2013-04-30 17:55:54",
"modified_by": "Administrator", "modified_by": "Administrator",
"owner": "Administrator" "owner": "Administrator"
}, },
{ {
"add_total_row": 1,
"doctype": "Report", "doctype": "Report",
"is_standard": "Yes", "is_standard": "Yes",
"name": "__common__", "name": "__common__",

View File

@ -18,7 +18,6 @@ def execute(filters=None):
and nowdate() or filters.get("report_date") and nowdate() or filters.get("report_date")
data = [] data = []
total_invoiced_amount = total_payment = total_outstanding = 0
for gle in entries: for gle in entries:
if cstr(gle.against_voucher) == gle.voucher_no or not gle.against_voucher \ if cstr(gle.against_voucher) == gle.voucher_no or not gle.against_voucher \
or [gle.against_voucher_type, gle.against_voucher] in entries_after_report_date: or [gle.against_voucher_type, gle.against_voucher] in entries_after_report_date:
@ -41,17 +40,9 @@ def execute(filters=None):
else: else:
ageing_based_on_date = gle.posting_date ageing_based_on_date = gle.posting_date
row += get_ageing_data(ageing_based_on_date, age_on, outstanding_amount) row += get_ageing_data(ageing_based_on_date, age_on, outstanding_amount)
# Add to total
total_invoiced_amount += flt(invoiced_amount)
total_payment += flt(payment_amount)
total_outstanding += flt(outstanding_amount)
data.append(row) data.append(row)
if data:
data.append(["", "", "", "", "", "", "Total", total_invoiced_amount, total_payment,
total_outstanding, "", "", "", ""])
return columns, data return columns, data
def get_columns(): def get_columns():

View File

@ -2,11 +2,12 @@
{ {
"creation": "2013-04-16 11:31:13", "creation": "2013-04-16 11:31:13",
"docstatus": 0, "docstatus": 0,
"modified": "2013-04-16 11:31:13", "modified": "2013-04-30 17:54:47",
"modified_by": "Administrator", "modified_by": "Administrator",
"owner": "Administrator" "owner": "Administrator"
}, },
{ {
"add_total_row": 1,
"doctype": "Report", "doctype": "Report",
"is_standard": "Yes", "is_standard": "Yes",
"name": "__common__", "name": "__common__",

View File

@ -0,0 +1,42 @@
wn.query_reports["Purchase Register"] = {
"filters": [
{
"fieldname":"from_date",
"label": "From Date",
"fieldtype": "Date",
"default": wn.defaults.get_user_default("year_start_date"),
"width": "80"
},
{
"fieldname":"to_date",
"label": "To Date",
"fieldtype": "Date",
"default": get_today()
},
{
"fieldname":"account",
"label": "Account",
"fieldtype": "Link",
"options": "Account",
"get_query": function() {
var company = wn.query_report.filters_by_name.company.get_value();
return {
"query": "accounts.utils.get_account_list",
"filters": {
"is_pl_account": "No",
"debit_or_credit": "Credit",
"company": company,
"master_type": "Supplier"
}
}
}
},
{
"fieldname":"company",
"label": "Company",
"fieldtype": "Link",
"options": "Company",
"default": sys_defaults.company
}
]
}

View File

@ -0,0 +1,147 @@
# ERPNext - web based ERP (http://erpnext.com)
# Copyright (C) 2012 Web Notes Technologies Pvt Ltd
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
from __future__ import unicode_literals
import webnotes
from webnotes.utils import flt
def execute(filters=None):
if not filters: filters = {}
columns, expense_accounts, tax_accounts = get_columns()
invoice_list = get_invoices(filters)
invoice_expense_map = get_invoice_expense_map(invoice_list)
invoice_tax_map = get_invoice_tax_map(invoice_list)
invoice_po_pr_map = get_invoice_po_pr_map(invoice_list)
account_map = get_account_details(invoice_list)
data = []
for inv in invoice_list:
# invoice details
purchase_order = ", ".join(invoice_po_pr_map.get(inv.name, {}).get("purchase_order", []))
purchase_receipt = ", ".join(invoice_po_pr_map.get(inv.name, {}).get("purchase_receipt", []))
row = [inv.name, inv.posting_date, inv.supplier, inv.credit_to,
account_map.get(inv.credit_to), inv.project_name, inv.bill_no, inv.bill_date,
inv.remarks, purchase_order, purchase_receipt]
# map expense values
for expense_acc in expense_accounts:
row.append(invoice_expense_map.get(inv.name, {}).get(expense_acc))
# net total
row.append(inv.net_total)
# tax account
for tax_acc in tax_accounts:
row.append(invoice_tax_map.get(inv.name, {}).get(tax_acc))
# total tax, grand total
row += [inv.total_tax, inv.grand_total]
data.append(row)
return columns, data
def get_columns():
"""return columns based on filters"""
columns = [
"Invoice:Link/Purchase Invoice:120", "Posting Date:Date:80", "Supplier:Link/Supplier:120",
"Supplier Account:Link/Account:120", "Account Group:LInk/Account:120",
"Project:Link/Project:80", "Bill No::120", "Bill Date:Date:80", "Remarks::150",
"Purchase Order:Link/Purchase Order:100", "Purchase Receipt:Link/Purchase Receipt:100"
]
expense_accounts = webnotes.conn.sql_list("""select distinct expense_head
from `tabPurchase Invoice Item` where docstatus = 1 and ifnull(expense_head, '') != ''
order by expense_head""")
tax_accounts = webnotes.conn.sql_list("""select distinct account_head
from `tabPurchase Taxes and Charges` where parenttype = 'Purchase Invoice'
and docstatus = 1 and ifnull(account_head, '') != '' order by account_head""")
columns = columns + [(account + ":Currency:120") for account in expense_accounts] + \
["Net Total:Currency:120"] + [(account + ":Currency:120") for account in tax_accounts] + \
["Total Tax:Currency:120"] + ["Grand Total:Currency:120"]
return columns, expense_accounts, tax_accounts
def get_conditions(filters):
conditions = ""
if filters.get("company"): conditions += " and company=%(company)s"
if filters.get("account"): conditions += " and account = %(account)s"
if filters.get("from_date"): conditions += " and posting_date>=%(from_date)s"
if filters.get("to_date"): conditions += " and posting_date<=%(to_date)s"
return conditions
def get_invoices(filters):
conditions = get_conditions(filters)
return webnotes.conn.sql("""select name, posting_date, credit_to, project_name, supplier,
bill_no, bill_date, remarks, net_total, total_tax, grand_total
from `tabPurchase Invoice` where docstatus = 1 %s
order by posting_date desc, name desc""" % conditions, filters, as_dict=1)
def get_invoice_expense_map(invoice_list):
expense_details = webnotes.conn.sql("""select parent, expense_head, sum(amount) as amount
from `tabPurchase Invoice Item` where parent in (%s) group by parent, expense_head""" %
', '.join(['%s']*len(invoice_list)), tuple([inv.name for inv in invoice_list]), as_dict=1)
invoice_expense_map = {}
for d in expense_details:
invoice_expense_map.setdefault(d.parent, webnotes._dict()).setdefault(d.expense_head, [])
invoice_expense_map[d.parent][d.expense_head] = flt(d.amount)
return invoice_expense_map
def get_invoice_tax_map(invoice_list):
tax_details = webnotes.conn.sql("""select parent, account_head, sum(tax_amount) as tax_amount
from `tabPurchase Taxes and Charges` where parent in (%s) group by parent, account_head""" %
', '.join(['%s']*len(invoice_list)), tuple([inv.name for inv in invoice_list]), as_dict=1)
invoice_tax_map = {}
for d in tax_details:
invoice_tax_map.setdefault(d.parent, webnotes._dict()).setdefault(d.account_head, [])
invoice_tax_map[d.parent][d.account_head] = flt(d.tax_amount)
return invoice_tax_map
def get_invoice_po_pr_map(invoice_list):
pi_items = webnotes.conn.sql("""select parent, purchase_order, purchase_receipt
from `tabPurchase Invoice Item` where parent in (%s)
and (ifnull(purchase_order, '') != '' or ifnull(purchase_receipt, '') != '')""" %
', '.join(['%s']*len(invoice_list)), tuple([inv.name for inv in invoice_list]), as_dict=1)
invoice_po_pr_map = {}
for d in pi_items:
if d.purchase_order:
invoice_po_pr_map.setdefault(d.parent, webnotes._dict()).setdefault(
"purchase_order", []).append(d.purchase_order)
if d.purchase_receipt:
invoice_po_pr_map.setdefault(d.parent, webnotes._dict()).setdefault(
"purchase_receipt", []).append(d.purchase_receipt)
return invoice_po_pr_map
def get_account_details(invoice_list):
account_map = {}
accounts = list(set([inv.credit_to for inv in invoice_list]))
for acc in webnotes.conn.sql("""select name, parent_account from tabAccount
where name in (%s)""" % ", ".join(["%s"]*len(accounts)), tuple(accounts), as_dict=1):
account_map.setdefault(acc.name, "")
account_map[acc.name] = acc.parent_account
return account_map

View File

@ -0,0 +1,22 @@
[
{
"creation": "2013-04-29 16:13:11",
"docstatus": 0,
"modified": "2013-04-30 17:51:19",
"modified_by": "Administrator",
"owner": "Administrator"
},
{
"add_total_row": 1,
"doctype": "Report",
"is_standard": "Yes",
"name": "__common__",
"ref_doctype": "Purchase Invoice",
"report_name": "Purchase Register",
"report_type": "Script Report"
},
{
"doctype": "Report",
"name": "Purchase Register"
}
]

View File

@ -0,0 +1,42 @@
wn.query_reports["Sales Register"] = {
"filters": [
{
"fieldname":"from_date",
"label": "From Date",
"fieldtype": "Date",
"default": wn.defaults.get_user_default("year_start_date"),
"width": "80"
},
{
"fieldname":"to_date",
"label": "To Date",
"fieldtype": "Date",
"default": get_today()
},
{
"fieldname":"account",
"label": "Account",
"fieldtype": "Link",
"options": "Account",
"get_query": function() {
var company = wn.query_report.filters_by_name.company.get_value();
return {
"query": "accounts.utils.get_account_list",
"filters": {
"is_pl_account": "No",
"debit_or_credit": "Debit",
"company": company,
"master_type": "Customer"
}
}
}
},
{
"fieldname":"company",
"label": "Company",
"fieldtype": "Link",
"options": "Company",
"default": sys_defaults.company
}
]
}

View File

@ -0,0 +1,161 @@
# ERPNext - web based ERP (http://erpnext.com)
# Copyright (C) 2012 Web Notes Technologies Pvt Ltd
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
from __future__ import unicode_literals
import webnotes
from webnotes.utils import flt
def execute(filters=None):
if not filters: filters = {}
columns, income_accounts, tax_accounts = get_columns()
invoice_list = get_invoices(filters)
invoice_income_map = get_invoice_income_map(invoice_list)
invoice_tax_map = get_invoice_tax_map(invoice_list)
invoice_so_dn_map = get_invoice_so_dn_map(invoice_list)
customer_map = get_customer_deatils(invoice_list)
account_map = get_account_details(invoice_list)
data = []
for inv in invoice_list:
# invoice details
sales_order = ", ".join(invoice_so_dn_map.get(inv.name, {}).get("sales_order", []))
delivery_note = ", ".join(invoice_so_dn_map.get(inv.name, {}).get("delivery_note", []))
# webnotes.errprint(customer_map.get(inv.customer, []))
row = [inv.name, inv.posting_date, inv.customer, inv.debit_to,
account_map.get(inv.debit_to), customer_map.get(inv.customer), inv.project_name,
inv.remarks, sales_order, delivery_note]
# map income values
for income_acc in income_accounts:
row.append(invoice_income_map.get(inv.name, {}).get(income_acc))
# net total
row.append(inv.net_total)
# tax account
for tax_acc in tax_accounts:
row.append(invoice_tax_map.get(inv.name, {}).get(tax_acc))
# total tax, grand total
row += [inv.other_charges_total, inv.grand_total]
data.append(row)
return columns, data
def get_columns():
"""return columns based on filters"""
columns = [
"Invoice:Link/Sales Invoice:120", "Posting Date:Date:80", "Customer:Link/Customer:120",
"Customer Account:Link/Account:120", "Account Group:LInk/Account:120",
"Territory:Link/Territory:80", "Project:Link/Project:80",
"Remarks::150", "Sales Order:Link/Sales Order:100", "Delivery Note:Link/Delivery Note:100"
]
income_accounts = webnotes.conn.sql_list("""select distinct income_account
from `tabSales Invoice Item` where docstatus = 1 order by income_account""")
tax_accounts = webnotes.conn.sql_list("""select distinct account_head
from `tabSales Taxes and Charges` where parenttype = 'Sales Invoice'
and docstatus = 1 order by account_head""")
columns = columns + [(account + ":Currency:120") for account in income_accounts] + \
["Net Total:Currency:120"] + [(account + ":Currency:120") for account in tax_accounts] + \
["Total Tax:Currency:120"] + ["Grand Total:Currency:120"]
return columns, income_accounts, tax_accounts
def get_conditions(filters):
conditions = ""
if filters.get("company"): conditions += " and company=%(company)s"
if filters.get("account"): conditions += " and account = %(account)s"
if filters.get("from_date"): conditions += " and posting_date>=%(from_date)s"
if filters.get("to_date"): conditions += " and posting_date<=%(to_date)s"
return conditions
def get_invoices(filters):
conditions = get_conditions(filters)
return webnotes.conn.sql("""select name, posting_date, debit_to, project_name, customer,
remarks, net_total, other_charges_total, grand_total
from `tabSales Invoice` where docstatus = 1 %s
order by posting_date desc, name desc""" % conditions, filters, as_dict=1)
def get_invoice_income_map(invoice_list):
income_details = webnotes.conn.sql("""select parent, income_account, sum(amount) as amount
from `tabSales Invoice Item` where parent in (%s) group by parent, income_account""" %
', '.join(['%s']*len(invoice_list)), tuple([inv.name for inv in invoice_list]), as_dict=1)
invoice_income_map = {}
for d in income_details:
invoice_income_map.setdefault(d.parent, webnotes._dict()).setdefault(d.income_account, [])
invoice_income_map[d.parent][d.income_account] = flt(d.amount)
return invoice_income_map
def get_invoice_tax_map(invoice_list):
tax_details = webnotes.conn.sql("""select parent, account_head, sum(tax_amount) as tax_amount
from `tabSales Taxes and Charges` where parent in (%s) group by parent, account_head""" %
', '.join(['%s']*len(invoice_list)), tuple([inv.name for inv in invoice_list]), as_dict=1)
invoice_tax_map = {}
for d in tax_details:
invoice_tax_map.setdefault(d.parent, webnotes._dict()).setdefault(d.account_head, [])
invoice_tax_map[d.parent][d.account_head] = flt(d.tax_amount)
return invoice_tax_map
def get_invoice_so_dn_map(invoice_list):
si_items = webnotes.conn.sql("""select parent, sales_order, delivery_note
from `tabSales Invoice Item` where parent in (%s)
and (ifnull(sales_order, '') != '' or ifnull(delivery_note, '') != '')""" %
', '.join(['%s']*len(invoice_list)), tuple([inv.name for inv in invoice_list]), as_dict=1)
invoice_so_dn_map = {}
for d in si_items:
if d.sales_order:
invoice_so_dn_map.setdefault(d.parent, webnotes._dict()).setdefault(
"sales_order", []).append(d.sales_order)
if d.delivery_note:
invoice_so_dn_map.setdefault(d.parent, webnotes._dict()).setdefault(
"delivery_note", []).append(d.delivery_note)
return invoice_so_dn_map
def get_customer_deatils(invoice_list):
customer_map = {}
customers = list(set([inv.customer for inv in invoice_list]))
for cust in webnotes.conn.sql("""select name, territory from `tabCustomer`
where name in (%s)""" % ", ".join(["%s"]*len(customers)), tuple(customers), as_dict=1):
customer_map.setdefault(cust.name, "")
customer_map[cust.name] = cust.territory
return customer_map
def get_account_details(invoice_list):
account_map = {}
accounts = list(set([inv.debit_to for inv in invoice_list]))
for acc in webnotes.conn.sql("""select name, parent_account from tabAccount
where name in (%s)""" % ", ".join(["%s"]*len(accounts)), tuple(accounts), as_dict=1):
account_map.setdefault(acc.name, "")
account_map[acc.name] = acc.parent_account
return account_map

View File

@ -0,0 +1,22 @@
[
{
"creation": "2013-04-23 18:15:29",
"docstatus": 0,
"modified": "2013-04-30 17:53:10",
"modified_by": "Administrator",
"owner": "Administrator"
},
{
"add_total_row": 1,
"doctype": "Report",
"is_standard": "Yes",
"name": "__common__",
"ref_doctype": "Sales Invoice",
"report_name": "Sales Register",
"report_type": "Script Report"
},
{
"doctype": "Report",
"name": "Sales Register"
}
]

View File

@ -1,29 +1,32 @@
[ [
{ {
"owner": "Administrator", "creation": "2012-05-14 18:05:41",
"docstatus": 0, "docstatus": 0,
"creation": "2012-04-03 12:49:50", "modified": "2013-04-30 14:49:06",
"modified_by": "Administrator", "modified_by": "Administrator",
"modified": "2012-04-03 12:49:50" "owner": "Administrator"
}, },
{ {
"description": "Bank Clearance report", "columns": "Journal Voucher\u0001ID,Journal Voucher Detail\u0001Account,Journal Voucher Detail\u0001Debit,Journal Voucher Detail\u0001Credit,Journal Voucher\u0001Clearance Date,Journal Voucher\u0001Cheque No,Journal Voucher\u0001Cheque Date,Journal Voucher\u0001Voucher Date,Journal Voucher\u0001Posting Date,Journal Voucher Detail\u0001Against Payable,Journal Voucher Detail\u0001Against Receivable",
"parent_doc_type": "Journal Voucher",
"module": "Accounts",
"standard": "Yes",
"sort_order": "DESC",
"filters": "{'Journal Voucher\u0001Submitted':1,'Journal Voucher\u0001Voucher Type':'','Journal Voucher\u0001Is Opening':'','Journal Voucher\u0001Fiscal Year':'','Journal Voucher\u0001Company':'','Journal Voucher\u0001TDS Applicable':'','Journal Voucher\u0001TDS Category':''}",
"dis_filters": "fiscal_year",
"doc_type": "Journal Voucher Detail",
"name": "__common__",
"doctype": "Search Criteria",
"sort_by": "ID",
"page_len": 50,
"criteria_name": "Bank Clearance report", "criteria_name": "Bank Clearance report",
"columns": "Journal Voucher\u0001ID,Journal Voucher Detail\u0001Account,Journal Voucher Detail\u0001Debit,Journal Voucher Detail\u0001Credit,Journal Voucher\u0001Clearance Date,Journal Voucher\u0001Cheque No,Journal Voucher\u0001Cheque Date,Journal Voucher\u0001Voucher Date,Journal Voucher\u0001Posting Date,Journal Voucher Detail\u0001Against Payable,Journal Voucher Detail\u0001Against Receivable" "custom_query": "",
"description": "Bank Clearance report",
"dis_filters": "fiscal_year",
"disabled": 0,
"doc_type": "Journal Voucher Detail",
"doctype": "Search Criteria",
"filters": "{'Journal Voucher\u0001Submitted':1,'Journal Voucher\u0001Voucher Type':'','Journal Voucher\u0001Is Opening':'','Journal Voucher\u0001Fiscal Year':'','Journal Voucher\u0001Company':'','Journal Voucher\u0001TDS Applicable':'','Journal Voucher\u0001TDS Category':''}",
"module": "Accounts",
"name": "__common__",
"page_len": 50,
"parent_doc_type": "Journal Voucher",
"report_script": null,
"sort_by": "ID",
"sort_order": "DESC",
"standard": "Yes"
}, },
{ {
"name": "bank_clearance_report", "doctype": "Search Criteria",
"doctype": "Search Criteria" "name": "bank_clearance_report"
} }
] ]

View File

@ -28,5 +28,5 @@ report.customize_filters = function() {
this.filter_fields_dict['Sales Invoice'+FILTER_SEP +'Grand Total <='].df.filter_hide = 1; this.filter_fields_dict['Sales Invoice'+FILTER_SEP +'Grand Total <='].df.filter_hide = 1;
this.filter_fields_dict['Sales Invoice'+FILTER_SEP +'Fiscal Year'].df.filter_hide = 1; this.filter_fields_dict['Sales Invoice'+FILTER_SEP +'Fiscal Year'].df.filter_hide = 1;
this.filter_fields_dict['Sales Invoice'+FILTER_SEP +'Sales Partner'].df.filter_hide = 1; this.filter_fields_dict['Sales Invoice'+FILTER_SEP +'Sales Partner'].df.filter_hide = 1;
this.filter_fields_dict['Sales Invoice'+FILTER_SEP +'Is Opening'].df.filter_hide = 1; this.filter_fields_dict['Sales Invoice'+FILTER_SEP +'Is Opening Entry'].df.filter_hide = 1;
} }

View File

@ -29,6 +29,7 @@ from controllers.stock_controller import StockController
class BuyingController(StockController): class BuyingController(StockController):
def validate(self): def validate(self):
super(BuyingController, self).validate() super(BuyingController, self).validate()
self.validate_stock_or_nonstock_items()
if self.meta.get_field("currency"): if self.meta.get_field("currency"):
self.company_currency = get_company_currency(self.doc.company) self.company_currency = get_company_currency(self.doc.company)
self.validate_conversion_rate("currency", "conversion_rate") self.validate_conversion_rate("currency", "conversion_rate")
@ -41,7 +42,25 @@ class BuyingController(StockController):
# set total in words # set total in words
self.set_total_in_words() self.set_total_in_words()
def validate_stock_or_nonstock_items(self):
items = [d.item_code for d in self.doclist.get({"parentfield": self.fname})]
if self.stock_items:
nonstock_items = list(set(items) - set(self.stock_items))
if nonstock_items:
webnotes.msgprint(_("Stock and non-stock items can not be entered in the same ") +
self.doc.doctype + _(""". You should make separate documents for them.
Stock Items: """) + ", ".join(self.stock_items) + _("""
Non-stock Items: """) + ", ".join(nonstock_items), raise_exception=1)
elif items and not self.stock_items:
tax_for_valuation = [d.account_head for d in
self.doclist.get({"parentfield": "purchase_tax_details"})
if d.category in ["Valuation", "Valuation and Total"]]
if tax_for_valuation:
webnotes.msgprint(_("""Tax Category can not be 'Valuation' or 'Valuation and Total'
as all items are non-stock items"""), raise_exception=1)
def update_item_details(self): def update_item_details(self):
for item in self.doclist.get({"parentfield": self.fname}): for item in self.doclist.get({"parentfield": self.fname}):
ret = get_item_details({ ret = get_item_details({

View File

@ -1,6 +1,8 @@
erpnext.updates = [ erpnext.updates = [
["10th April", ["Redesigned File Uploads and added File Manager in Setup"]], ["18th April", ["Cost Center: Set a default Cost Center for a Company"]],
["12th April", ["Employee: List of Leave Approvers who can approve the Employee's Leave Applications"]], ["12th April", ["Employee: List of Leave Approvers who can approve the Employee's Leave Applications"]],
["10th April", ["Redesigned File Uploads and added File Manager in Setup"]],
["3rd April", ["Update Manager: Open source users can update their ERPNext instance from Setup > Update Manager"]],
["27th March", ["Rename multiple items together. Go to Setup > Rename Tool"]], ["27th March", ["Rename multiple items together. Go to Setup > Rename Tool"]],
["26th March", ["Added project to Stock Ledger and Balance", ["26th March", ["Added project to Stock Ledger and Balance",
"Added Default Cash Account in Company."]], "Added Default Cash Account in Company."]],

View File

@ -59,27 +59,22 @@ cur_frm.fields_dict["bom_operations"].grid.on_row_delete = function(cdt, cdn){
set_operation_no(doc); set_operation_no(doc);
} }
cur_frm.cscript.item = function(doc, dt, dn) { cur_frm.add_fetch("item", "description", "description");
if (doc.item) { cur_frm.add_fetch("item", "stock_uom", "uom");
get_server_fields('get_item_details', doc.item, '', doc, dt, dn, 1);
}
}
cur_frm.cscript.workstation = function(doc,dt,dn) { cur_frm.cscript.workstation = function(doc,dt,dn) {
var d = locals[dt][dn]; var d = locals[dt][dn];
if (d.workstation) { wn.model.with_doc("Workstation", d.workstation, function(i, v) {
var callback = function(r, rt) { d.hour_rate = v.hour_rate;
calculate_op_cost(doc, dt, dn); refresh_field("hour_rate");
calculate_total(doc); calculate_op_cost(doc);
} calculate_total(doc);
get_server_fields('get_workstation_details', d.workstation, });
'bom_operations', doc, dt, dn, 1, callback);
}
} }
cur_frm.cscript.hour_rate = function(doc, dt, dn) { cur_frm.cscript.hour_rate = function(doc, dt, dn) {
calculate_op_cost(doc, dt, dn); calculate_op_cost(doc);
calculate_total(doc); calculate_total(doc);
} }
@ -114,7 +109,7 @@ var get_bom_material_detail= function(doc, cdt, cdn) {
$.extend(d, r.message); $.extend(d, r.message);
refresh_field("bom_materials"); refresh_field("bom_materials");
doc = locals[doc.doctype][doc.name]; doc = locals[doc.doctype][doc.name];
calculate_rm_cost(doc, cdt, cdn); calculate_rm_cost(doc);
calculate_total(doc); calculate_total(doc);
}, },
freeze: true freeze: true
@ -124,7 +119,7 @@ var get_bom_material_detail= function(doc, cdt, cdn) {
cur_frm.cscript.qty = function(doc, cdt, cdn) { cur_frm.cscript.qty = function(doc, cdt, cdn) {
calculate_rm_cost(doc, cdt, cdn); calculate_rm_cost(doc);
calculate_total(doc); calculate_total(doc);
} }
@ -134,12 +129,12 @@ cur_frm.cscript.rate = function(doc, cdt, cdn) {
msgprint("You can not change rate if BOM mentioned agianst any item"); msgprint("You can not change rate if BOM mentioned agianst any item");
get_bom_material_detail(doc, cdt, cdn); get_bom_material_detail(doc, cdt, cdn);
} else { } else {
calculate_rm_cost(doc, cdt, cdn); calculate_rm_cost(doc);
calculate_total(doc); calculate_total(doc);
} }
} }
var calculate_op_cost = function(doc, dt, dn) { var calculate_op_cost = function(doc) {
var op = getchildren('BOM Operation', doc.name, 'bom_operations'); var op = getchildren('BOM Operation', doc.name, 'bom_operations');
total_op_cost = 0; total_op_cost = 0;
for(var i=0;i<op.length;i++) { for(var i=0;i<op.length;i++) {
@ -151,7 +146,7 @@ var calculate_op_cost = function(doc, dt, dn) {
refresh_field('operating_cost'); refresh_field('operating_cost');
} }
var calculate_rm_cost = function(doc, dt, dn) { var calculate_rm_cost = function(doc) {
var rm = getchildren('BOM Item', doc.name, 'bom_materials'); var rm = getchildren('BOM Item', doc.name, 'bom_materials');
total_rm_cost = 0; total_rm_cost = 0;
for(var i=0;i<rm.length;i++) { for(var i=0;i<rm.length;i++) {
@ -201,7 +196,7 @@ cur_frm.fields_dict['bom_materials'].grid.get_field('bom_no').get_query = functi
} }
cur_frm.cscript.validate = function(doc, dt, dn) { cur_frm.cscript.validate = function(doc, dt, dn) {
calculate_op_cost(doc, dt, dn); calculate_op_cost(doc);
calculate_rm_cost(doc, dt, dn); calculate_rm_cost(doc);
calculate_total(doc); calculate_total(doc);
} }

View File

@ -32,7 +32,7 @@ class DocType:
def autoname(self): def autoname(self):
last_name = sql("""select max(name) from `tabBOM` last_name = sql("""select max(name) from `tabBOM`
where name like 'BOM/%s/%%'""" % self.doc.item) where name like "BOM/%s/%%" """ % cstr(self.doc.item).replace('"', '\\"'))
if last_name: if last_name:
idx = cint(cstr(last_name[0][0]).split('/')[-1]) + 1 idx = cint(cstr(last_name[0][0]).split('/')[-1]) + 1
else: else:
@ -44,10 +44,11 @@ class DocType:
self.validate_main_item() self.validate_main_item()
self.validate_operations() self.validate_operations()
self.validate_materials() self.validate_materials()
self.set_bom_material_details()
self.calculate_cost()
def on_update(self): def on_update(self):
self.check_recursion() self.check_recursion()
self.calculate_cost()
self.update_exploded_items() self.update_exploded_items()
self.doc.save() self.doc.save()
@ -67,21 +68,13 @@ class DocType:
self.manage_default_bom() self.manage_default_bom()
def get_item_det(self, item_code): def get_item_det(self, item_code):
item = sql("""select name, is_asset_item, is_purchase_item, docstatus, description, item = webnotes.conn.sql("""select name, is_asset_item, is_purchase_item,
is_sub_contracted_item, stock_uom, default_bom, docstatus, description, is_sub_contracted_item, stock_uom, default_bom,
last_purchase_rate, standard_rate, is_manufactured_item last_purchase_rate, standard_rate, is_manufactured_item
from `tabItem` where item_code = %s""", item_code, as_dict = 1) from `tabItem` where name=%s""", item_code, as_dict = 1)
return item return item
def get_item_details(self, item_code):
res = sql("""select description, stock_uom as uom
from `tabItem` where item_code = %s""", item_code, as_dict = 1)
return res and res[0] or {}
def get_workstation_details(self,workstation):
return {'hour_rate': webnotes.conn.get_value("Workstation", workstation, "hour_rate")}
def validate_rm_item(self, item): def validate_rm_item(self, item):
if item[0]['name'] == self.doc.item: if item[0]['name'] == self.doc.item:
msgprint("Item_code: %s in materials tab cannot be same as FG Item", msgprint("Item_code: %s in materials tab cannot be same as FG Item",
@ -89,32 +82,42 @@ class DocType:
if not item or item[0]['docstatus'] == 2: if not item or item[0]['docstatus'] == 2:
msgprint("Item %s does not exist in system" % item[0]['item_code'], raise_exception = 1) msgprint("Item %s does not exist in system" % item[0]['item_code'], raise_exception = 1)
def get_bom_material_detail(self): def set_bom_material_details(self):
for item in self.doclist.get({"parentfield": "bom_materials"}):
ret = self.get_bom_material_detail({ "item_code": item.item_code, "bom_no": item.bom_no,
"qty": item.qty })
for r in ret:
if not item.fields.get(r):
item.fields[r] = ret[r]
def get_bom_material_detail(self, args=None):
""" Get raw material details like uom, desc and rate""" """ Get raw material details like uom, desc and rate"""
arg = webnotes.form_dict.get('args') if not args:
import json args = webnotes.form_dict.get('args')
arg = json.loads(arg) import json
args = json.loads(args)
item = self.get_item_det(arg['item_code'])
item = self.get_item_det(args['item_code'])
self.validate_rm_item(item) self.validate_rm_item(item)
arg['bom_no'] = arg['bom_no'] or item and cstr(item[0]['default_bom']) or '' args['bom_no'] = args['bom_no'] or item and cstr(item[0]['default_bom']) or ''
arg.update(item[0]) args.update(item[0])
rate = self.get_rm_rate(arg) rate = self.get_rm_rate(args)
ret_item = { ret_item = {
'description' : item and arg['description'] or '', 'description' : item and args['description'] or '',
'stock_uom' : item and arg['stock_uom'] or '', 'stock_uom' : item and args['stock_uom'] or '',
'bom_no' : arg['bom_no'], 'bom_no' : args['bom_no'],
'rate' : rate 'rate' : rate
} }
return ret_item return ret_item
def get_rm_rate(self, arg): def get_rm_rate(self, arg):
""" Get raw material rate as per selected method, if bom exists takes bom cost """ """ Get raw material rate as per selected method, if bom exists takes bom cost """
rate = 0
if arg['bom_no']: if arg['bom_no']:
rate = self.get_bom_unitcost(arg['bom_no']) rate = self.get_bom_unitcost(arg['bom_no'])
elif arg and (arg['is_purchase_item'] == 'Yes' or arg['is_sub_contracted_item'] == 'Yes'): elif arg and (arg['is_purchase_item'] == 'Yes' or arg['is_sub_contracted_item'] == 'Yes'):
@ -183,11 +186,14 @@ class DocType:
if not item: if not item:
msgprint("Item %s does not exists in the system or expired." % msgprint("Item %s does not exists in the system or expired." %
self.doc.item, raise_exception = 1) self.doc.item, raise_exception = 1)
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':
msgprint("""As Item: %s is not a manufactured / sub-contracted item, \ msgprint("""As Item: %s is not a manufactured / sub-contracted item, \
you can not make BOM for it""" % self.doc.item, raise_exception = 1) you can not make BOM for it""" % self.doc.item, raise_exception = 1)
else:
ret = webnotes.conn.get_value("Item", self.doc.item, ["description", "stock_uom"])
self.doc.description = ret[0]
self.doc.uom = ret[1]
def validate_operations(self): def validate_operations(self):
""" Check duplicate operation no""" """ Check duplicate operation no"""
@ -209,7 +215,7 @@ class DocType:
msgprint("""Operation no: %s against item: %s at row no: %s \ msgprint("""Operation no: %s against item: %s at row no: %s \
is not present at Operations table""" % is not present at Operations table""" %
(m.operation_no, m.item_code, m.idx), raise_exception = 1) (m.operation_no, m.item_code, m.idx), raise_exception = 1)
item = self.get_item_det(m.item_code) item = self.get_item_det(m.item_code)
if item[0]['is_manufactured_item'] == 'Yes': if item[0]['is_manufactured_item'] == 'Yes':
if not m.bom_no: if not m.bom_no:
@ -293,9 +299,10 @@ class DocType:
"""Update workstation rate and calculates totals""" """Update workstation rate and calculates totals"""
total_op_cost = 0 total_op_cost = 0
for d in getlist(self.doclist, 'bom_operations'): for d in getlist(self.doclist, 'bom_operations'):
if d.workstation and not d.hour_rate:
d.hour_rate = webnotes.conn.get_value("Workstation", d.workstation, "hour_rate")
if d.hour_rate and d.time_in_mins: if d.hour_rate and d.time_in_mins:
d.operating_cost = flt(d.hour_rate) * flt(d.time_in_mins) / 60.0 d.operating_cost = flt(d.hour_rate) * flt(d.time_in_mins) / 60.0
d.save()
total_op_cost += flt(d.operating_cost) total_op_cost += flt(d.operating_cost)
self.doc.operating_cost = total_op_cost self.doc.operating_cost = total_op_cost
@ -307,7 +314,6 @@ class DocType:
d.rate = self.get_bom_unitcost(d.bom_no) d.rate = self.get_bom_unitcost(d.bom_no)
d.amount = flt(d.rate) * flt(d.qty) d.amount = flt(d.rate) * flt(d.qty)
d.qty_consumed_per_unit = flt(d.qty) / flt(self.doc.quantity) d.qty_consumed_per_unit = flt(d.qty) / flt(self.doc.quantity)
d.save()
total_rm_cost += d.amount total_rm_cost += d.amount
self.doc.raw_material_cost = total_rm_cost self.doc.raw_material_cost = total_rm_cost

Binary file not shown.

View File

@ -4,27 +4,37 @@ def execute():
webnotes.reload_doc("core", "doctype", "file_data") webnotes.reload_doc("core", "doctype", "file_data")
webnotes.reset_perms("File Data") webnotes.reset_perms("File Data")
singles = webnotes.conn.sql_list("""select name from tabDocType singles = get_single_doctypes()
where ifnull(issingle,0)=1""")
for doctype in webnotes.conn.sql_list("""select parent from tabDocField where for doctype in webnotes.conn.sql_list("""select parent from tabDocField where
fieldname='file_list' and fieldtype='Text'"""): fieldname='file_list'"""):
if doctype in singles: update_file_list(doctype, singles)
doc = webnotes.doc(doctype, doctype)
if doc.file_list:
update_for_doc(doctype, doc)
webnotes.conn.set_value(doctype, None, "file_list", None)
else:
try:
for doc in webnotes.conn.sql("""select name, file_list from `tab%s` where
ifnull(file_list, '')!=''""" % doctype, as_dict=True):
update_for_doc(doctype, doc)
webnotes.conn.commit()
webnotes.conn.sql("""alter table `tab%s` drop column file_list""" % doctype)
except Exception, e:
if e.args[0]!=1054: raise e
webnotes.conn.sql("""delete from tabDocField where fieldname='file_list' webnotes.conn.sql("""delete from tabDocField where fieldname='file_list'
and parent=%s""", doctype) and parent=%s""", doctype)
# export_to_files([["DocType", doctype]])
def get_single_doctypes():
return webnotes.conn.sql_list("""select name from tabDocType
where ifnull(issingle,0)=1""")
def update_file_list(doctype, singles):
if doctype in singles:
doc = webnotes.doc(doctype, doctype)
if doc.file_list:
update_for_doc(doctype, doc)
webnotes.conn.set_value(doctype, None, "file_list", None)
else:
try:
for doc in webnotes.conn.sql("""select name, file_list from `tab%s` where
ifnull(file_list, '')!=''""" % doctype, as_dict=True):
update_for_doc(doctype, doc)
webnotes.conn.commit()
webnotes.conn.sql("""alter table `tab%s` drop column `file_list`""" % doctype)
except Exception, e:
print webnotes.getTraceback()
if (e.args and e.args[0]!=1054) or not e.args:
raise e
def update_for_doc(doctype, doc): def update_for_doc(doctype, doc):
for filedata in doc.file_list.split("\n"): for filedata in doc.file_list.split("\n"):
@ -43,10 +53,21 @@ def update_for_doc(doctype, doc):
exists = False exists = False
if exists: if exists:
webnotes.conn.sql("""update `tabFile Data` if webnotes.conn.exists("File Data", fileid):
set attached_to_doctype=%s, attached_to_name=%s try:
where name=%s""", (doctype, doc.name, fileid)) fd = webnotes.bean("File Data", fileid)
if not (fd.doc.attached_to_doctype and fd.doc.attached_to_name):
fd.doc.attached_to_doctype = doctype
fd.doc.attached_to_name = doc.name
fd.save()
else:
fd = webnotes.bean("File Data", copy=fd.doclist)
fd.doc.attached_to_doctype = doctype
fd.doc.attached_to_name = doc.name
fd.doc.name = None
fd.insert()
except webnotes.DuplicateEntryError:
pass
else: else:
webnotes.conn.sql("""delete from `tabFile Data` where name=%s""", webnotes.conn.sql("""delete from `tabFile Data` where name=%s""",
fileid) fileid)

View File

@ -0,0 +1,18 @@
import webnotes
def execute():
from patches.april_2013.p05_update_file_data import update_file_list, get_single_doctypes
singles = get_single_doctypes()
for doctype in webnotes.conn.sql_list("""select table_name from `information_schema`.`columns`
where table_schema=%s and column_name='file_list'""", webnotes.conn.cur_db_name):
doctype = doctype[3:]
if not webnotes.conn.exists("DocType", doctype): continue
update_file_list(doctype, singles)
webnotes.conn.sql("""delete from `tabCustom Field` where fieldname='file_list'
and parent=%s""", doctype)
webnotes.conn.sql("""delete from `tabDocField` where fieldname='file_list'
and parent=%s""", doctype)

View File

@ -0,0 +1,4 @@
import webnotes
def execute():
from patches.january_2013 import rebuild_tree
rebuild_tree.execute()

View File

@ -246,4 +246,7 @@ patch_list = [
"execute:webnotes.delete_doc('DocType Mapper', 'Delivery Note-Packing Slip')", "execute:webnotes.delete_doc('DocType Mapper', 'Delivery Note-Packing Slip')",
"patches.april_2013.p07_rename_cost_center_other_charges", "patches.april_2013.p07_rename_cost_center_other_charges",
"patches.april_2013.p06_default_cost_center", "patches.april_2013.p06_default_cost_center",
"execute:webnotes.reset_perms('File Data')",
"patches.april_2013.p07_update_file_data_2",
"patches.april_2013.rebuild_sales_browser",
] ]

View File

@ -5,4 +5,4 @@ import webnotes
@webnotes.whitelist() @webnotes.whitelist()
def get_time_log_list(doctype, txt, searchfield, start, page_len, filters): def get_time_log_list(doctype, txt, searchfield, start, page_len, filters):
return webnotes.conn.get_values("Time Log", filters, ["name", "activity_type", "owner"], debug=True) return webnotes.conn.get_values("Time Log", filters, ["name", "activity_type", "owner"])

View File

@ -85,6 +85,7 @@ def backup_to_dropbox():
os.path.basename(backup.backup_path_db)) os.path.basename(backup.backup_path_db))
upload_file_to_dropbox(filename, "/database", dropbox_client) upload_file_to_dropbox(filename, "/database", dropbox_client)
webnotes.conn.close()
response = dropbox_client.metadata("/files") response = dropbox_client.metadata("/files")
# upload files to files folder # upload files to files folder
@ -108,6 +109,7 @@ def backup_to_dropbox():
did_not_upload.append(filename) did_not_upload.append(filename)
error_log.append(cstr(e)) error_log.append(cstr(e))
webnotes.connect()
return did_not_upload, list(set(error_log)) return did_not_upload, list(set(error_log))
def get_dropbox_session(): def get_dropbox_session():

View File

@ -34,7 +34,6 @@ def get_gdrive_authorize_url():
"authorize_url": authorize_url, "authorize_url": authorize_url,
} }
@webnotes.whitelist()
def upload_files(name, mimetype, service, folder_id): def upload_files(name, mimetype, service, folder_id):
if not webnotes.conn: if not webnotes.conn:
webnotes.connect() webnotes.connect()
@ -78,6 +77,9 @@ def backup_to_gdrive():
did_not_upload = [] did_not_upload = []
error_log = [] error_log = []
files_folder_id = webnotes.conn.get_value("Backup Manager", None, "files_folder_id")
webnotes.conn.close()
path = os.path.join(get_base_path(), "public", "files") path = os.path.join(get_base_path(), "public", "files")
for filename in os.listdir(path): for filename in os.listdir(path):
found = False found = False
@ -91,9 +93,7 @@ def backup_to_gdrive():
#Compare Local File with Server File #Compare Local File with Server File
param = {} param = {}
children = drive_service.children().list( children = drive_service.children().list(folderId=files_folder_id, **param).execute()
folderId=webnotes.conn.get_value("Backup Manager", None, "files_folder_id"),
**param).execute()
for child in children.get('items', []): for child in children.get('items', []):
file = drive_service.files().get(fileId=child['id']).execute() file = drive_service.files().get(fileId=child['id']).execute()
if filename == file['title'] and size == int(file['fileSize']): if filename == file['title'] and size == int(file['fileSize']):
@ -101,12 +101,12 @@ def backup_to_gdrive():
break break
if not found: if not found:
try: try:
upload_files(filepath, mimetype, drive_service, upload_files(filepath, mimetype, drive_service, files_folder_id)
webnotes.conn.get_value("Backup Manager", None, "files_folder_id"))
except Exception, e: except Exception, e:
did_not_upload.append(filename) did_not_upload.append(filename)
error_log.append(cstr(e)) error_log.append(cstr(e))
webnotes.connect()
return did_not_upload, list(set(error_log)) return did_not_upload, list(set(error_log))
def get_gdrive_flow(): def get_gdrive_flow():

View File

@ -29,12 +29,12 @@ class DocType:
def get_transactions(self, arg=None): def get_transactions(self, arg=None):
return { return {
"transactions": "\n".join([''] + [i[0] for i in "transactions": "\n".join([''] + sorted(list(set(
sql("""select `tabDocField`.`parent` webnotes.conn.sql_list("""select parent
FROM `tabDocField`, `tabDocType` from `tabDocField` where fieldname='naming_series'""")
WHERE `tabDocField`.`fieldname` = 'naming_series' + webnotes.conn.sql_list("""select dt from `tabCustom Field`
and `tabDocType`.name=`tabDocField`.parent where fieldname='naming_series'""")
order by `tabDocField`.parent""")]), )))),
"prefixes": "\n".join([''] + [i[0] for i in "prefixes": "\n".join([''] + [i[0] for i in
sql("""select name from tabSeries""")]) sql("""select name from tabSeries""")])
} }
@ -89,7 +89,6 @@ class DocType:
'property': prop, 'property': prop,
'value': prop_dict[prop], 'value': prop_dict[prop],
'property_type': 'Select', 'property_type': 'Select',
'select_doctype': doctype
}) })
ps.save(1) ps.save(1)
@ -101,11 +100,18 @@ class DocType:
from core.doctype.doctype.doctype import DocType from core.doctype.doctype.doctype import DocType
dt = DocType() dt = DocType()
parent = sql("""select dt.name from `tabDocField` df, `tabDocType` dt parent = list(set(
where dt.name = df.parent and df.fieldname='naming_series' and dt.name != %s""", webnotes.conn.sql_list("""select dt.name
self.doc.select_doc_for_series) from `tabDocField` df, `tabDocType` dt
sr = ([webnotes.model.doctype.get_property(p[0], 'options', 'naming_series'), p[0]] where dt.name = df.parent and df.fieldname='naming_series' and dt.name != %s""",
for p in parent) self.doc.select_doc_for_series)
+ webnotes.conn.sql_list("""select dt.name
from `tabCustom Field` df, `tabDocType` dt
where dt.name = df.dt and df.fieldname='naming_series' and dt.name != %s""",
self.doc.select_doc_for_series)
))
sr = [[webnotes.model.doctype.get_property(p, 'options', 'naming_series'), p]
for p in parent]
options = self.scrub_options_list(self.doc.set_options.split("\n")) options = self.scrub_options_list(self.doc.set_options.split("\n"))
for series in options: for series in options:
dt.validate_series(series, self.doc.select_doc_for_series) dt.validate_series(series, self.doc.select_doc_for_series)

View File

@ -326,6 +326,17 @@ if (sys_defaults.auto_inventory_accounting) {
} }
// cost center // cost center
cur_frm.cscript.cost_center = function(doc, cdt, cdn){
var d = locals[cdt][cdn];
if(d.cost_center) {
var cl = getchildren('Delivery Note Item', doc.name, cur_frm.cscript.fname, doc.doctype);
for(var i = 0; i < cl.length; i++){
if(!cl[i].cost_center) cl[i].cost_center = d.cost_center;
}
}
refresh_field(cur_frm.cscript.fname);
}
cur_frm.fields_dict.delivery_note_details.grid.get_field("cost_center").get_query = function(doc) { cur_frm.fields_dict.delivery_note_details.grid.get_field("cost_center").get_query = function(doc) {
return { return {
query: "accounts.utils.get_cost_center_list", query: "accounts.utils.get_cost_center_list",

View File

@ -55,12 +55,13 @@ class DocType(DocListController):
ch.conversion_factor = 1 ch.conversion_factor = 1
def check_stock_uom_with_bin(self): def check_stock_uom_with_bin(self):
bin = webnotes.conn.sql("select stock_uom from `tabBin` where item_code = %s", if not self.doc.fields.get("__islocal"):
self.doc.item_code) bin = webnotes.conn.sql("select stock_uom from `tabBin` where item_code = %s",
if self.doc.stock_uom and bin and cstr(bin[0][0]) \ self.doc.name)
and cstr(bin[0][0]) != cstr(self.doc.stock_uom): if self.doc.stock_uom and bin and cstr(bin[0][0]) \
msgprint(_("Please Update Stock UOM with the help of Stock UOM Replace Utility."), and cstr(bin[0][0]) != cstr(self.doc.stock_uom):
raise_exception=1) msgprint(_("Please Update Stock UOM with the help of Stock UOM Replace Utility."),
raise_exception=1)
def validate_conversion_factor(self): def validate_conversion_factor(self):
check_list = [] check_list = []
@ -154,13 +155,14 @@ class DocType(DocListController):
def validate_barcode(self): def validate_barcode(self):
if self.doc.barcode: if self.doc.barcode:
duplicate = webnotes.conn.sql("select name from tabItem where barcode = %s and name != %s", (self.doc.barcode, self.doc.name)) duplicate = webnotes.conn.sql("""select name from tabItem where barcode = %s
and name != %s""", (self.doc.barcode, self.doc.name))
if duplicate: if duplicate:
msgprint("Barcode: %s already used in item: %s" % msgprint("Barcode: %s already used in item: %s" %
(self.doc.barcode, cstr(duplicate[0][0])), raise_exception = 1) (self.doc.barcode, cstr(duplicate[0][0])), raise_exception = 1)
def check_non_asset_warehouse(self): def check_non_asset_warehouse(self):
if self.doc.is_asset_item == "Yes": if not self.doc.__islocal and self.doc.is_asset_item == "Yes":
existing_qty = webnotes.conn.sql("select t1.warehouse, t1.actual_qty from tabBin t1, tabWarehouse t2 where t1.item_code=%s and (t2.warehouse_type!='Fixed Asset' or t2.warehouse_type is null) and t1.warehouse=t2.name and t1.actual_qty > 0", self.doc.name) existing_qty = webnotes.conn.sql("select t1.warehouse, t1.actual_qty from tabBin t1, tabWarehouse t2 where t1.item_code=%s and (t2.warehouse_type!='Fixed Asset' or t2.warehouse_type is null) and t1.warehouse=t2.name and t1.actual_qty > 0", self.doc.name)
for e in existing_qty: for e in existing_qty:
msgprint("%s Units exist in Warehouse %s, which is not an Asset Warehouse." % msgprint("%s Units exist in Warehouse %s, which is not an Asset Warehouse." %

View File

@ -95,6 +95,8 @@ erpnext.StockAgeing = erpnext.StockGridReport.extend({
this.data = [].concat(this._data); this.data = [].concat(this._data);
this.serialized_buying_rates = this.get_serialized_buying_rates();
$.each(this.data, function(i, d) { $.each(this.data, function(i, d) {
me.reset_item_values(d); me.reset_item_values(d);
}); });

View File

@ -29,17 +29,13 @@ $.extend(cur_frm.cscript, {
erpnext.hide_naming_series(); erpnext.hide_naming_series();
cur_frm.cscript.make_listing(doc); cur_frm.cscript.make_listing(doc);
if(!doc.__islocal) { if(!doc.__islocal) {
if(in_list(user_roles,'System Manager')) { if(user_roles.indexOf("Support Manager")!==-1) {
if(doc.status!='Closed') cur_frm.add_custom_button('Close Ticket', cur_frm.cscript['Close Ticket']); if(doc.status!='Closed') cur_frm.add_custom_button('Close Ticket', cur_frm.cscript['Close Ticket']);
if(doc.status=='Closed') cur_frm.add_custom_button('Re-Open Ticket', cur_frm.cscript['Re-Open Ticket']); if(doc.status=='Closed') cur_frm.add_custom_button('Re-Open Ticket', cur_frm.cscript['Re-Open Ticket']);
}else if(doc.allocated_to) {
cur_frm.set_df_property('status','read_only', 1);
if(user==doc.allocated_to && doc.status!='Closed') cur_frm.add_custom_button('Close Ticket', cur_frm.cscript['Close Ticket']);
} }
cur_frm.set_df_property('subject','read_only', 1); cur_frm.toggle_enable(["subject", "raised_by"], false);
cur_frm.set_df_property('description','hidden', 1); cur_frm.toggle_display("description", false);
cur_frm.set_df_property('raised_by','read_only', 1);
} }
refresh_field('status'); refresh_field('status');
}, },

View File

@ -45,6 +45,10 @@ class DocType(TransactionBase):
def validate(self): def validate(self):
self.update_status() self.update_status()
if self.doc.status == "Closed":
from webnotes.widgets.form.assign_to import clear
clear(self.doc.doctype, self.doc.name)
def on_communication_sent(self, comm): def on_communication_sent(self, comm):
webnotes.conn.set(self.doc, 'status', 'Waiting for Customer') webnotes.conn.set(self.doc, 'status', 'Waiting for Customer')
if comm.lead and not self.doc.lead: if comm.lead and not self.doc.lead:

View File

@ -34,7 +34,8 @@ def upload(select_doctype=None, rows=None):
rename_log = [] rename_log = []
for row in rows: for row in rows:
if len(row) > 2: # if row has some content
if len(row) > 1 and row[0] and row[1]:
try: try:
if rename_doc(select_doctype, row[0], row[1]): if rename_doc(select_doctype, row[0], row[1]):
rename_log.append(_("Successful: ") + row[0] + " -> " + row[1]) rename_log.append(_("Successful: ") + row[0] + " -> " + row[1])
@ -45,5 +46,5 @@ def upload(select_doctype=None, rows=None):
rename_log.append("<span style='color: RED'>" + \ rename_log.append("<span style='color: RED'>" + \
_("Failed: ") + row[0] + " -> " + row[1] + "</span>") _("Failed: ") + row[0] + " -> " + row[1] + "</span>")
rename_log.append("<span style='margin-left: 20px;'>" + repr(e) + "</span>") rename_log.append("<span style='margin-left: 20px;'>" + repr(e) + "</span>")
return rename_log return rename_log