From e55fbfc0909ccafd9d4d9169cd12328ee2a9ca24 Mon Sep 17 00:00:00 2001 From: Pratik Vyas Date: Wed, 18 Sep 2013 11:10:59 +0530 Subject: [PATCH 001/200] remove sql = --- accounts/doctype/account/account.py | 1 - accounts/doctype/bank_reconciliation/bank_reconciliation.py | 1 - accounts/doctype/gl_entry/gl_entry.py | 1 - accounts/doctype/mis_control/mis_control.py | 1 - .../doctype/period_closing_voucher/period_closing_voucher.py | 1 - accounts/doctype/purchase_invoice/purchase_invoice.py | 1 - .../purchase_taxes_and_charges_master.py | 1 - buying/doctype/purchase_common/purchase_common.py | 1 - buying/doctype/purchase_order/purchase_order.py | 1 - buying/doctype/supplier/supplier.py | 1 - home/doctype/feed/feed.py | 1 - hr/doctype/attendance/attendance.py | 1 - hr/doctype/employee/employee.py | 1 - hr/doctype/holiday_list/holiday_list.py | 1 - hr/doctype/leave_allocation/leave_allocation.py | 1 - hr/doctype/leave_control_panel/leave_control_panel.py | 1 - hr/doctype/salary_manager/salary_manager.py | 1 - hr/doctype/salary_slip/salary_slip.py | 1 - hr/doctype/salary_structure/salary_structure.py | 1 - manufacturing/doctype/bom/bom.py | 1 - manufacturing/doctype/production_order/production_order.py | 1 - .../production_planning_tool/production_planning_tool.py | 1 - manufacturing/doctype/workstation/workstation.py | 1 - projects/doctype/task/task.py | 1 - selling/doctype/customer/customer.py | 1 - selling/doctype/lead/lead.py | 1 - selling/doctype/opportunity/opportunity.py | 1 - selling/doctype/quotation/quotation.py | 1 - selling/doctype/sales_order/sales_order.py | 1 - selling/doctype/sms_center/sms_center.py | 1 - setup/doctype/authorization_control/authorization_control.py | 1 - setup/doctype/authorization_rule/authorization_rule.py | 1 - setup/doctype/company/company.py | 1 - setup/doctype/customer_group/customer_group.py | 1 - setup/doctype/email_settings/email_settings.py | 1 - setup/doctype/naming_series/naming_series.py | 1 - setup/doctype/notification_control/notification_control.py | 1 - setup/doctype/print_heading/print_heading.py | 1 - setup/doctype/sales_partner/sales_partner.py | 1 - stock/doctype/bin/bin.py | 1 - stock/doctype/delivery_note/delivery_note.py | 1 - stock/doctype/landed_cost_wizard/landed_cost_wizard.py | 1 - stock/doctype/purchase_receipt/purchase_receipt.py | 1 - stock/doctype/stock_entry/stock_entry.py | 1 - stock/doctype/stock_ledger/stock_ledger.py | 1 - .../stock_uom_replace_utility/stock_uom_replace_utility.py | 1 - stock/doctype/warehouse/warehouse.py | 1 - support/doctype/customer_issue/customer_issue.py | 1 - support/doctype/maintenance_schedule/maintenance_schedule.py | 1 - support/doctype/maintenance_visit/maintenance_visit.py | 1 - utilities/doctype/sms_control/sms_control.py | 4 +--- 51 files changed, 1 insertion(+), 53 deletions(-) diff --git a/accounts/doctype/account/account.py b/accounts/doctype/account/account.py index a6038ddd930..7d8bed9b32a 100644 --- a/accounts/doctype/account/account.py +++ b/accounts/doctype/account/account.py @@ -7,7 +7,6 @@ import webnotes from webnotes.utils import flt, fmt_money from webnotes import msgprint, _ -sql = webnotes.conn.sql get_value = webnotes.conn.get_value class DocType: diff --git a/accounts/doctype/bank_reconciliation/bank_reconciliation.py b/accounts/doctype/bank_reconciliation/bank_reconciliation.py index 479b57955cf..ce15e57a0ec 100644 --- a/accounts/doctype/bank_reconciliation/bank_reconciliation.py +++ b/accounts/doctype/bank_reconciliation/bank_reconciliation.py @@ -10,7 +10,6 @@ from webnotes.model.doc import addchild from webnotes.model.bean import getlist, copy_doclist from webnotes import msgprint -sql = webnotes.conn.sql diff --git a/accounts/doctype/gl_entry/gl_entry.py b/accounts/doctype/gl_entry/gl_entry.py index 9c1cf3fa670..aa0f11b1780 100644 --- a/accounts/doctype/gl_entry/gl_entry.py +++ b/accounts/doctype/gl_entry/gl_entry.py @@ -8,7 +8,6 @@ from webnotes.utils import flt, fmt_money, getdate from webnotes.model.code import get_obj from webnotes import msgprint, _ -sql = webnotes.conn.sql class DocType: def __init__(self,d,dl): diff --git a/accounts/doctype/mis_control/mis_control.py b/accounts/doctype/mis_control/mis_control.py index 84350dcb722..bb582704907 100644 --- a/accounts/doctype/mis_control/mis_control.py +++ b/accounts/doctype/mis_control/mis_control.py @@ -11,7 +11,6 @@ from webnotes import session, msgprint import webnotes.defaults -sql = webnotes.conn.sql from accounts.utils import get_balance_on, get_fiscal_year diff --git a/accounts/doctype/period_closing_voucher/period_closing_voucher.py b/accounts/doctype/period_closing_voucher/period_closing_voucher.py index c214a211c08..9df653ad884 100644 --- a/accounts/doctype/period_closing_voucher/period_closing_voucher.py +++ b/accounts/doctype/period_closing_voucher/period_closing_voucher.py @@ -11,7 +11,6 @@ from webnotes.model.bean import copy_doclist from webnotes.model.code import get_obj from webnotes import msgprint -sql = webnotes.conn.sql diff --git a/accounts/doctype/purchase_invoice/purchase_invoice.py b/accounts/doctype/purchase_invoice/purchase_invoice.py index 05383235614..0c5a277a0ce 100644 --- a/accounts/doctype/purchase_invoice/purchase_invoice.py +++ b/accounts/doctype/purchase_invoice/purchase_invoice.py @@ -12,7 +12,6 @@ from setup.utils import get_company_currency import webnotes.defaults -sql = webnotes.conn.sql from controllers.buying_controller import BuyingController class DocType(BuyingController): diff --git a/accounts/doctype/purchase_taxes_and_charges_master/purchase_taxes_and_charges_master.py b/accounts/doctype/purchase_taxes_and_charges_master/purchase_taxes_and_charges_master.py index a4534aefd62..0a32fb972d6 100644 --- a/accounts/doctype/purchase_taxes_and_charges_master/purchase_taxes_and_charges_master.py +++ b/accounts/doctype/purchase_taxes_and_charges_master/purchase_taxes_and_charges_master.py @@ -8,7 +8,6 @@ from webnotes.model import db_exists from webnotes.model.bean import copy_doclist from webnotes.model.code import get_obj -sql = webnotes.conn.sql diff --git a/buying/doctype/purchase_common/purchase_common.py b/buying/doctype/purchase_common/purchase_common.py index 9b6dc6c9ab7..dfe2af57f51 100644 --- a/buying/doctype/purchase_common/purchase_common.py +++ b/buying/doctype/purchase_common/purchase_common.py @@ -10,7 +10,6 @@ from webnotes import msgprint, _ from buying.utils import get_last_purchase_details -sql = webnotes.conn.sql from controllers.buying_controller import BuyingController class DocType(BuyingController): diff --git a/buying/doctype/purchase_order/purchase_order.py b/buying/doctype/purchase_order/purchase_order.py index 367517719c1..951ff8b70e7 100644 --- a/buying/doctype/purchase_order/purchase_order.py +++ b/buying/doctype/purchase_order/purchase_order.py @@ -9,7 +9,6 @@ from webnotes.model.bean import getlist from webnotes.model.code import get_obj from webnotes import msgprint -sql = webnotes.conn.sql from controllers.buying_controller import BuyingController class DocType(BuyingController): diff --git a/buying/doctype/supplier/supplier.py b/buying/doctype/supplier/supplier.py index 15e1d625f9a..2c1d173ea72 100644 --- a/buying/doctype/supplier/supplier.py +++ b/buying/doctype/supplier/supplier.py @@ -9,7 +9,6 @@ from webnotes.utils import cint from webnotes import msgprint, _ from webnotes.model.doc import make_autoname -sql = webnotes.conn.sql from utilities.transaction_base import TransactionBase diff --git a/home/doctype/feed/feed.py b/home/doctype/feed/feed.py index 25abf5798a0..ebee5c4ce75 100644 --- a/home/doctype/feed/feed.py +++ b/home/doctype/feed/feed.py @@ -7,7 +7,6 @@ import webnotes from webnotes.model import db_exists from webnotes.model.bean import copy_doclist -sql = webnotes.conn.sql diff --git a/hr/doctype/attendance/attendance.py b/hr/doctype/attendance/attendance.py index 7b82bc524b0..124d3621a5a 100644 --- a/hr/doctype/attendance/attendance.py +++ b/hr/doctype/attendance/attendance.py @@ -7,7 +7,6 @@ import webnotes from webnotes.utils import getdate, nowdate from webnotes import msgprint, _ -sql = webnotes.conn.sql class DocType: def __init__(self, doc, doclist=[]): diff --git a/hr/doctype/employee/employee.py b/hr/doctype/employee/employee.py index e28e02d81bb..e8396eb5392 100644 --- a/hr/doctype/employee/employee.py +++ b/hr/doctype/employee/employee.py @@ -8,7 +8,6 @@ from webnotes.utils import getdate, validate_email_add, cstr from webnotes.model.doc import make_autoname from webnotes import msgprint, _ -sql = webnotes.conn.sql class DocType: def __init__(self,doc,doclist=[]): diff --git a/hr/doctype/holiday_list/holiday_list.py b/hr/doctype/holiday_list/holiday_list.py index 81d18f336e1..100c1403fad 100644 --- a/hr/doctype/holiday_list/holiday_list.py +++ b/hr/doctype/holiday_list/holiday_list.py @@ -10,7 +10,6 @@ from webnotes.model.doc import addchild, make_autoname from webnotes.model.bean import copy_doclist from webnotes import msgprint -sql = webnotes.conn.sql import datetime diff --git a/hr/doctype/leave_allocation/leave_allocation.py b/hr/doctype/leave_allocation/leave_allocation.py index 1c856fa3352..8e226908d8b 100755 --- a/hr/doctype/leave_allocation/leave_allocation.py +++ b/hr/doctype/leave_allocation/leave_allocation.py @@ -5,7 +5,6 @@ from __future__ import unicode_literals import webnotes from webnotes.utils import cint, flt from webnotes import msgprint -sql = webnotes.conn.sql class DocType: def __init__(self, doc, doclist): diff --git a/hr/doctype/leave_control_panel/leave_control_panel.py b/hr/doctype/leave_control_panel/leave_control_panel.py index 30b52ba8898..640432109f1 100644 --- a/hr/doctype/leave_control_panel/leave_control_panel.py +++ b/hr/doctype/leave_control_panel/leave_control_panel.py @@ -9,7 +9,6 @@ from webnotes.model.doc import Document from webnotes.model.code import get_obj from webnotes import msgprint -sql = webnotes.conn.sql diff --git a/hr/doctype/salary_manager/salary_manager.py b/hr/doctype/salary_manager/salary_manager.py index 0eadca14c42..ecc829f87ab 100644 --- a/hr/doctype/salary_manager/salary_manager.py +++ b/hr/doctype/salary_manager/salary_manager.py @@ -11,7 +11,6 @@ from webnotes.model.bean import getlist, copy_doclist from webnotes.model.code import get_obj from webnotes import msgprint -sql = webnotes.conn.sql diff --git a/hr/doctype/salary_slip/salary_slip.py b/hr/doctype/salary_slip/salary_slip.py index 36d7ceba84e..71042731704 100644 --- a/hr/doctype/salary_slip/salary_slip.py +++ b/hr/doctype/salary_slip/salary_slip.py @@ -11,7 +11,6 @@ from webnotes.model.code import get_obj from webnotes import msgprint, _ from setup.utils import get_company_currency -sql = webnotes.conn.sql from utilities.transaction_base import TransactionBase diff --git a/hr/doctype/salary_structure/salary_structure.py b/hr/doctype/salary_structure/salary_structure.py index 50b0160d9ae..c3cd93d48c6 100644 --- a/hr/doctype/salary_structure/salary_structure.py +++ b/hr/doctype/salary_structure/salary_structure.py @@ -8,7 +8,6 @@ from webnotes.utils import cstr, flt from webnotes.model.doc import addchild, make_autoname from webnotes import msgprint, _ -sql = webnotes.conn.sql class DocType: def __init__(self,doc,doclist=[]): diff --git a/manufacturing/doctype/bom/bom.py b/manufacturing/doctype/bom/bom.py index 9a566123c78..84a3d6c13b9 100644 --- a/manufacturing/doctype/bom/bom.py +++ b/manufacturing/doctype/bom/bom.py @@ -9,7 +9,6 @@ from webnotes.model.bean import getlist from webnotes.model.code import get_obj from webnotes import msgprint, _ -sql = webnotes.conn.sql class DocType: diff --git a/manufacturing/doctype/production_order/production_order.py b/manufacturing/doctype/production_order/production_order.py index 6a133e78fa0..28adc65e36c 100644 --- a/manufacturing/doctype/production_order/production_order.py +++ b/manufacturing/doctype/production_order/production_order.py @@ -8,7 +8,6 @@ from webnotes.utils import cstr, flt, nowdate from webnotes.model.code import get_obj from webnotes import msgprint, _ -sql = webnotes.conn.sql class OverProductionError(webnotes.ValidationError): pass diff --git a/manufacturing/doctype/production_planning_tool/production_planning_tool.py b/manufacturing/doctype/production_planning_tool/production_planning_tool.py index 766f2ac233c..c150be3ff69 100644 --- a/manufacturing/doctype/production_planning_tool/production_planning_tool.py +++ b/manufacturing/doctype/production_planning_tool/production_planning_tool.py @@ -9,7 +9,6 @@ from webnotes.model.bean import getlist from webnotes.model.code import get_obj from webnotes import msgprint, _ -sql = webnotes.conn.sql class DocType: def __init__(self, doc, doclist=[]): diff --git a/manufacturing/doctype/workstation/workstation.py b/manufacturing/doctype/workstation/workstation.py index 35e2c1f06b2..56833a9e5b0 100644 --- a/manufacturing/doctype/workstation/workstation.py +++ b/manufacturing/doctype/workstation/workstation.py @@ -8,7 +8,6 @@ from webnotes.utils import flt from webnotes.model import db_exists from webnotes.model.bean import copy_doclist -sql = webnotes.conn.sql diff --git a/projects/doctype/task/task.py b/projects/doctype/task/task.py index 6cd1ba8636e..856be5cc889 100644 --- a/projects/doctype/task/task.py +++ b/projects/doctype/task/task.py @@ -9,7 +9,6 @@ from webnotes.model import db_exists from webnotes.model.bean import copy_doclist from webnotes import msgprint -sql = webnotes.conn.sql class DocType: def __init__(self,doc,doclist=[]): diff --git a/selling/doctype/customer/customer.py b/selling/doctype/customer/customer.py index d3a263fbb98..0c2bf616ddd 100644 --- a/selling/doctype/customer/customer.py +++ b/selling/doctype/customer/customer.py @@ -9,7 +9,6 @@ from webnotes.model.doc import Document, make_autoname from webnotes import msgprint, _ import webnotes.defaults -sql = webnotes.conn.sql from utilities.transaction_base import TransactionBase diff --git a/selling/doctype/lead/lead.py b/selling/doctype/lead/lead.py index da11410f24f..c0ef242baa8 100644 --- a/selling/doctype/lead/lead.py +++ b/selling/doctype/lead/lead.py @@ -7,7 +7,6 @@ from webnotes import _ from webnotes.utils import cstr, validate_email_add, cint, extract_email_id from webnotes import session, msgprint -sql = webnotes.conn.sql from controllers.selling_controller import SellingController diff --git a/selling/doctype/opportunity/opportunity.py b/selling/doctype/opportunity/opportunity.py index b265356a4d5..df6861a7731 100644 --- a/selling/doctype/opportunity/opportunity.py +++ b/selling/doctype/opportunity/opportunity.py @@ -8,7 +8,6 @@ from webnotes.utils import cstr, getdate, cint from webnotes.model.bean import getlist from webnotes import msgprint -sql = webnotes.conn.sql from utilities.transaction_base import TransactionBase diff --git a/selling/doctype/quotation/quotation.py b/selling/doctype/quotation/quotation.py index 44a67fa45cd..8ac0d1925ad 100644 --- a/selling/doctype/quotation/quotation.py +++ b/selling/doctype/quotation/quotation.py @@ -9,7 +9,6 @@ from webnotes.model.bean import getlist from webnotes.model.code import get_obj from webnotes import _, msgprint -sql = webnotes.conn.sql from controllers.selling_controller import SellingController diff --git a/selling/doctype/sales_order/sales_order.py b/selling/doctype/sales_order/sales_order.py index 37314845adc..5043a77d76c 100644 --- a/selling/doctype/sales_order/sales_order.py +++ b/selling/doctype/sales_order/sales_order.py @@ -11,7 +11,6 @@ from webnotes.model.code import get_obj from webnotes import msgprint from webnotes.model.mapper import get_mapped_doclist -sql = webnotes.conn.sql from controllers.selling_controller import SellingController diff --git a/selling/doctype/sms_center/sms_center.py b/selling/doctype/sms_center/sms_center.py index c3b5ac03714..8db20b0275a 100644 --- a/selling/doctype/sms_center/sms_center.py +++ b/selling/doctype/sms_center/sms_center.py @@ -10,7 +10,6 @@ from webnotes.model.bean import copy_doclist from webnotes.model.code import get_obj from webnotes import msgprint -sql = webnotes.conn.sql # ---------- diff --git a/setup/doctype/authorization_control/authorization_control.py b/setup/doctype/authorization_control/authorization_control.py index ddf0791bde1..26f7705af3e 100644 --- a/setup/doctype/authorization_control/authorization_control.py +++ b/setup/doctype/authorization_control/authorization_control.py @@ -9,7 +9,6 @@ from webnotes.model.bean import getlist from webnotes import session, msgprint from setup.utils import get_company_currency -sql = webnotes.conn.sql from utilities.transaction_base import TransactionBase diff --git a/setup/doctype/authorization_rule/authorization_rule.py b/setup/doctype/authorization_rule/authorization_rule.py index 3d2de4776d6..5192ebf769f 100644 --- a/setup/doctype/authorization_rule/authorization_rule.py +++ b/setup/doctype/authorization_rule/authorization_rule.py @@ -9,7 +9,6 @@ from webnotes.model import db_exists from webnotes.model.bean import copy_doclist from webnotes import msgprint -sql = webnotes.conn.sql diff --git a/setup/doctype/company/company.py b/setup/doctype/company/company.py index eeff2d1bef2..bb0ee1baebc 100644 --- a/setup/doctype/company/company.py +++ b/setup/doctype/company/company.py @@ -10,7 +10,6 @@ from webnotes.model.doc import Document from webnotes.model.code import get_obj import webnotes.defaults -sql = webnotes.conn.sql class DocType: def __init__(self,d,dl): diff --git a/setup/doctype/customer_group/customer_group.py b/setup/doctype/customer_group/customer_group.py index 0940e1f0b3c..8b68cc50e48 100644 --- a/setup/doctype/customer_group/customer_group.py +++ b/setup/doctype/customer_group/customer_group.py @@ -5,7 +5,6 @@ from __future__ import unicode_literals import webnotes from webnotes import msgprint -sql = webnotes.conn.sql from webnotes.utils.nestedset import DocTypeNestedSet class DocType(DocTypeNestedSet): diff --git a/setup/doctype/email_settings/email_settings.py b/setup/doctype/email_settings/email_settings.py index 219501eb13f..aa511eefcdd 100644 --- a/setup/doctype/email_settings/email_settings.py +++ b/setup/doctype/email_settings/email_settings.py @@ -3,7 +3,6 @@ from __future__ import unicode_literals import webnotes -sql = webnotes.conn.sql from webnotes.utils import cint diff --git a/setup/doctype/naming_series/naming_series.py b/setup/doctype/naming_series/naming_series.py index 9cc4de294b8..6312801fe8a 100644 --- a/setup/doctype/naming_series/naming_series.py +++ b/setup/doctype/naming_series/naming_series.py @@ -8,7 +8,6 @@ from webnotes.utils import cstr from webnotes import msgprint import webnotes.model.doctype -sql = webnotes.conn.sql class DocType: def __init__(self, d, dl): diff --git a/setup/doctype/notification_control/notification_control.py b/setup/doctype/notification_control/notification_control.py index 6133d9b7019..23493624dd4 100644 --- a/setup/doctype/notification_control/notification_control.py +++ b/setup/doctype/notification_control/notification_control.py @@ -6,7 +6,6 @@ import webnotes from webnotes import msgprint -sql = webnotes.conn.sql class DocType: def __init__(self,d,dl): diff --git a/setup/doctype/print_heading/print_heading.py b/setup/doctype/print_heading/print_heading.py index ba7114a22d9..134aaaf013d 100644 --- a/setup/doctype/print_heading/print_heading.py +++ b/setup/doctype/print_heading/print_heading.py @@ -7,7 +7,6 @@ import webnotes from webnotes.model import db_exists from webnotes.model.bean import copy_doclist -sql = webnotes.conn.sql diff --git a/setup/doctype/sales_partner/sales_partner.py b/setup/doctype/sales_partner/sales_partner.py index 0d7e12d9998..8915ff1cc0f 100644 --- a/setup/doctype/sales_partner/sales_partner.py +++ b/setup/doctype/sales_partner/sales_partner.py @@ -5,7 +5,6 @@ from __future__ import unicode_literals import webnotes from webnotes.utils import cint, cstr, filter_strip_join -sql = webnotes.conn.sql class DocType: def __init__(self, doc, doclist=None): diff --git a/stock/doctype/bin/bin.py b/stock/doctype/bin/bin.py index 146191f9b15..954ef783a4f 100644 --- a/stock/doctype/bin/bin.py +++ b/stock/doctype/bin/bin.py @@ -5,7 +5,6 @@ from __future__ import unicode_literals import webnotes from webnotes.utils import add_days, cint,flt, nowdate, get_url_to_form, formatdate from webnotes import msgprint, _ -sql = webnotes.conn.sql import webnotes.defaults diff --git a/stock/doctype/delivery_note/delivery_note.py b/stock/doctype/delivery_note/delivery_note.py index 042b197f134..ce06ce3d0bc 100644 --- a/stock/doctype/delivery_note/delivery_note.py +++ b/stock/doctype/delivery_note/delivery_note.py @@ -13,7 +13,6 @@ from webnotes.model.mapper import get_mapped_doclist -sql = webnotes.conn.sql from controllers.selling_controller import SellingController diff --git a/stock/doctype/landed_cost_wizard/landed_cost_wizard.py b/stock/doctype/landed_cost_wizard/landed_cost_wizard.py index 0cdad4d949a..52756320544 100644 --- a/stock/doctype/landed_cost_wizard/landed_cost_wizard.py +++ b/stock/doctype/landed_cost_wizard/landed_cost_wizard.py @@ -9,7 +9,6 @@ from webnotes.model.bean import getlist from webnotes.model.code import get_obj from webnotes import msgprint -sql = webnotes.conn.sql class DocType: diff --git a/stock/doctype/purchase_receipt/purchase_receipt.py b/stock/doctype/purchase_receipt/purchase_receipt.py index f7cfcff093a..084f30cd593 100644 --- a/stock/doctype/purchase_receipt/purchase_receipt.py +++ b/stock/doctype/purchase_receipt/purchase_receipt.py @@ -10,7 +10,6 @@ from webnotes.model.code import get_obj from webnotes import msgprint import webnotes.defaults -sql = webnotes.conn.sql from controllers.buying_controller import BuyingController class DocType(BuyingController): diff --git a/stock/doctype/stock_entry/stock_entry.py b/stock/doctype/stock_entry/stock_entry.py index 6a61461ac53..b5e1edf09c2 100644 --- a/stock/doctype/stock_entry/stock_entry.py +++ b/stock/doctype/stock_entry/stock_entry.py @@ -15,7 +15,6 @@ from stock.stock_ledger import get_previous_sle from controllers.queries import get_match_cond import json -sql = webnotes.conn.sql class NotUpdateStockError(webnotes.ValidationError): pass class StockOverReturnError(webnotes.ValidationError): pass diff --git a/stock/doctype/stock_ledger/stock_ledger.py b/stock/doctype/stock_ledger/stock_ledger.py index 10fb7617f0f..1624b007d3c 100644 --- a/stock/doctype/stock_ledger/stock_ledger.py +++ b/stock/doctype/stock_ledger/stock_ledger.py @@ -11,7 +11,6 @@ from webnotes.model.code import get_obj from webnotes import session, msgprint from stock.utils import get_valid_serial_nos -sql = webnotes.conn.sql class DocType: def __init__(self, doc, doclist=[]): diff --git a/stock/doctype/stock_uom_replace_utility/stock_uom_replace_utility.py b/stock/doctype/stock_uom_replace_utility/stock_uom_replace_utility.py index 321e3c98077..2ec9debf7f2 100644 --- a/stock/doctype/stock_uom_replace_utility/stock_uom_replace_utility.py +++ b/stock/doctype/stock_uom_replace_utility/stock_uom_replace_utility.py @@ -10,7 +10,6 @@ from webnotes.model.bean import copy_doclist from webnotes.model.code import get_obj from webnotes import msgprint, _ -sql = webnotes.conn.sql class DocType: def __init__(self, d, dl=[]): diff --git a/stock/doctype/warehouse/warehouse.py b/stock/doctype/warehouse/warehouse.py index 0de27fe647f..b23f043a3da 100644 --- a/stock/doctype/warehouse/warehouse.py +++ b/stock/doctype/warehouse/warehouse.py @@ -8,7 +8,6 @@ from webnotes.utils import flt, validate_email_add from webnotes.model.code import get_obj from webnotes import msgprint -sql = webnotes.conn.sql class DocType: def __init__(self, doc, doclist=[]): diff --git a/support/doctype/customer_issue/customer_issue.py b/support/doctype/customer_issue/customer_issue.py index 910e9b845d3..3773cdf3605 100644 --- a/support/doctype/customer_issue/customer_issue.py +++ b/support/doctype/customer_issue/customer_issue.py @@ -7,7 +7,6 @@ import webnotes from webnotes import session, msgprint from webnotes.utils import today -sql = webnotes.conn.sql from utilities.transaction_base import TransactionBase diff --git a/support/doctype/maintenance_schedule/maintenance_schedule.py b/support/doctype/maintenance_schedule/maintenance_schedule.py index 59d3f8eb383..4bb121767c7 100644 --- a/support/doctype/maintenance_schedule/maintenance_schedule.py +++ b/support/doctype/maintenance_schedule/maintenance_schedule.py @@ -9,7 +9,6 @@ from webnotes.model.doc import addchild from webnotes.model.bean import getlist from webnotes import msgprint -sql = webnotes.conn.sql from utilities.transaction_base import TransactionBase, delete_events diff --git a/support/doctype/maintenance_visit/maintenance_visit.py b/support/doctype/maintenance_visit/maintenance_visit.py index bf8767becec..dbb2880ac91 100644 --- a/support/doctype/maintenance_visit/maintenance_visit.py +++ b/support/doctype/maintenance_visit/maintenance_visit.py @@ -8,7 +8,6 @@ from webnotes.utils import cstr from webnotes.model.bean import getlist from webnotes import msgprint -sql = webnotes.conn.sql from utilities.transaction_base import TransactionBase diff --git a/utilities/doctype/sms_control/sms_control.py b/utilities/doctype/sms_control/sms_control.py index 9c2319fcfb9..d72db529dd8 100644 --- a/utilities/doctype/sms_control/sms_control.py +++ b/utilities/doctype/sms_control/sms_control.py @@ -10,8 +10,6 @@ from webnotes.model.doc import Document from webnotes import msgprint from webnotes.model.bean import getlist, copy_doclist -sql = webnotes.conn.sql - class DocType: def __init__(self, doc, doclist=[]): self.doc = doc @@ -119,4 +117,4 @@ class DocType: sl.message = arg['message'] sl.no_of_requested_sms = len(arg['receiver_list']) sl.no_of_sent_sms = sent_sms - sl.save(new=1) \ No newline at end of file + sl.save(new=1) From 5e16a69b35fc76d8412ce332bb5eeed387af0c5d Mon Sep 17 00:00:00 2001 From: Pratik Vyas Date: Wed, 18 Sep 2013 12:20:53 +0530 Subject: [PATCH 002/200] mass replace sql with webnotes.conn.sql --- accounts/doctype/account/account.py | 14 ++++---- .../bank_reconciliation.py | 4 +-- accounts/doctype/gl_entry/gl_entry.py | 8 ++--- accounts/doctype/mis_control/mis_control.py | 12 +++---- .../period_closing_voucher.py | 16 +++++----- .../purchase_invoice/purchase_invoice.py | 18 +++++------ .../purchase_common/purchase_common.py | 28 ++++++++-------- .../doctype/purchase_order/purchase_order.py | 6 ++-- buying/doctype/supplier/supplier.py | 20 ++++++------ hr/doctype/attendance/attendance.py | 6 ++-- .../leave_allocation/leave_allocation.py | 10 +++--- .../leave_control_panel.py | 2 +- hr/doctype/salary_manager/salary_manager.py | 12 +++---- .../salary_manager/test_salary_manager.py | 14 ++++---- hr/doctype/salary_slip/salary_slip.py | 14 ++++---- .../salary_structure/salary_structure.py | 8 ++--- manufacturing/doctype/bom/bom.py | 18 +++++------ .../production_order/production_order.py | 6 ++-- .../production_planning_tool.py | 20 ++++++------ .../doctype/workstation/workstation.py | 4 +-- projects/doctype/task/task.py | 4 +-- selling/doctype/customer/customer.py | 8 ++--- selling/doctype/lead/lead.py | 2 +- selling/doctype/opportunity/opportunity.py | 12 +++---- selling/doctype/quotation/quotation.py | 14 ++++---- selling/doctype/sales_order/sales_order.py | 32 +++++++++---------- selling/doctype/sms_center/sms_center.py | 8 ++--- .../authorization_control.py | 30 ++++++++--------- .../authorization_rule/authorization_rule.py | 8 ++--- .../doctype/customer_group/customer_group.py | 6 ++-- setup/doctype/naming_series/naming_series.py | 6 ++-- .../notification_control.py | 2 +- setup/doctype/sales_partner/sales_partner.py | 2 +- stock/doctype/bin/bin.py | 2 +- stock/doctype/delivery_note/delivery_note.py | 12 +++---- .../landed_cost_wizard/landed_cost_wizard.py | 14 ++++---- .../purchase_receipt/purchase_receipt.py | 8 ++--- stock/doctype/stock_entry/stock_entry.py | 14 ++++---- .../stock_uom_replace_utility.py | 12 +++---- stock/doctype/warehouse/warehouse.py | 10 +++--- .../doctype/customer_issue/customer_issue.py | 2 +- .../maintenance_schedule.py | 16 +++++----- .../maintenance_visit/maintenance_visit.py | 10 +++--- utilities/doctype/contact/contact.py | 15 ++++----- utilities/doctype/sms_control/sms_control.py | 2 +- 45 files changed, 245 insertions(+), 246 deletions(-) diff --git a/accounts/doctype/account/account.py b/accounts/doctype/account/account.py index 7d8bed9b32a..65274d7ba9c 100644 --- a/accounts/doctype/account/account.py +++ b/accounts/doctype/account/account.py @@ -32,7 +32,7 @@ class DocType: def validate_parent(self): """Fetch Parent Details and validation for account not to be created under ledger""" if self.doc.parent_account: - par = sql("""select name, group_or_ledger, is_pl_account, debit_or_credit + par = webnotes.conn.sql("""select name, group_or_ledger, is_pl_account, debit_or_credit from tabAccount where name =%s""", self.doc.parent_account) if not par: msgprint("Parent account does not exists", raise_exception=1) @@ -60,7 +60,7 @@ class DocType: def validate_duplicate_account(self): if self.doc.fields.get('__islocal') or not self.doc.name: company_abbr = webnotes.conn.get_value("Company", self.doc.company, "abbr") - if sql("""select name from tabAccount where name=%s""", + if webnotes.conn.sql("""select name from tabAccount where name=%s""", (self.doc.account_name + " - " + company_abbr)): msgprint("Account Name: %s already exists, please rename" % self.doc.account_name, raise_exception=1) @@ -97,12 +97,12 @@ class DocType: # Check if any previous balance exists def check_gle_exists(self): - exists = sql("""select name from `tabGL Entry` where account = %s + exists = webnotes.conn.sql("""select name from `tabGL Entry` where account = %s and ifnull(is_cancelled, 'No') = 'No'""", self.doc.name) return exists and exists[0][0] or '' def check_if_child_exists(self): - return sql("""select name from `tabAccount` where parent_account = %s + return webnotes.conn.sql("""select name from `tabAccount` where parent_account = %s and docstatus != 2""", self.doc.name) def validate_mandatory(self): @@ -141,7 +141,7 @@ class DocType: # Get credit limit credit_limit_from = 'Customer' - cr_limit = sql("""select t1.credit_limit from tabCustomer t1, `tabAccount` t2 + cr_limit = webnotes.conn.sql("""select t1.credit_limit from tabCustomer t1, `tabAccount` t2 where t2.name=%s and t1.name = t2.master_name""", account) credit_limit = cr_limit and flt(cr_limit[0][0]) or 0 if not credit_limit: @@ -173,7 +173,7 @@ class DocType: self.update_nsm_model() # delete all cancelled gl entry of this account - sql("""delete from `tabGL Entry` where account = %s and + webnotes.conn.sql("""delete from `tabGL Entry` where account = %s and ifnull(is_cancelled, 'No') = 'Yes'""", self.doc.name) def on_rename(self, new, old, merge=False): @@ -185,7 +185,7 @@ class DocType: # rename account name new_account_name = " - ".join(parts[:-1]) - sql("update `tabAccount` set account_name = %s where name = %s", (new_account_name, old)) + webnotes.conn.sql("update `tabAccount` set account_name = %s where name = %s", (new_account_name, old)) if merge: new_name = " - ".join(parts) diff --git a/accounts/doctype/bank_reconciliation/bank_reconciliation.py b/accounts/doctype/bank_reconciliation/bank_reconciliation.py index ce15e57a0ec..132358ef83a 100644 --- a/accounts/doctype/bank_reconciliation/bank_reconciliation.py +++ b/accounts/doctype/bank_reconciliation/bank_reconciliation.py @@ -22,7 +22,7 @@ class DocType: msgprint("Bank Account, From Date and To Date are Mandatory") return - dl = sql("select t1.name, t1.cheque_no, t1.cheque_date, t2.debit, t2.credit, t1.posting_date, t2.against_account from `tabJournal Voucher` t1, `tabJournal Voucher Detail` t2 where t2.parent = t1.name and t2.account = %s and (clearance_date is null or clearance_date = '0000-00-00' or clearance_date = '') and t1.posting_date >= %s and t1.posting_date <= %s and t1.docstatus=1", (self.doc.bank_account, self.doc.from_date, self.doc.to_date)) + dl = webnotes.conn.sql("select t1.name, t1.cheque_no, t1.cheque_date, t2.debit, t2.credit, t1.posting_date, t2.against_account from `tabJournal Voucher` t1, `tabJournal Voucher Detail` t2 where t2.parent = t1.name and t2.account = %s and (clearance_date is null or clearance_date = '0000-00-00' or clearance_date = '') and t1.posting_date >= %s and t1.posting_date <= %s and t1.docstatus=1", (self.doc.bank_account, self.doc.from_date, self.doc.to_date)) self.doclist = self.doc.clear_table(self.doclist, 'entries') self.doc.total_amount = 0.0 @@ -46,7 +46,7 @@ class DocType: msgprint("Clearance Date can not be before Cheque Date (Row #%s)" % d.idx, raise_exception=1) - sql("""update `tabJournal Voucher` + webnotes.conn.sql("""update `tabJournal Voucher` set clearance_date = %s, modified = %s where name=%s""", (d.clearance_date, nowdate(), d.voucher_id)) vouchers.append(d.voucher_id) diff --git a/accounts/doctype/gl_entry/gl_entry.py b/accounts/doctype/gl_entry/gl_entry.py index aa0f11b1780..5cde97a7064 100644 --- a/accounts/doctype/gl_entry/gl_entry.py +++ b/accounts/doctype/gl_entry/gl_entry.py @@ -63,7 +63,7 @@ class DocType: tot_outstanding = 0 #needed when there is no GL Entry in the system for that acc head if (self.doc.voucher_type=='Journal Voucher' or self.doc.voucher_type=='Sales Invoice') \ and (master_type =='Customer' and master_name): - dbcr = sql("""select sum(debit), sum(credit) from `tabGL Entry` + dbcr = webnotes.conn.sql("""select sum(debit), sum(credit) from `tabGL Entry` where account = '%s' and is_cancelled='No'""" % self.doc.account) if dbcr: tot_outstanding = flt(dbcr[0][0]) - flt(dbcr[0][1]) + \ @@ -80,7 +80,7 @@ class DocType: def validate_account_details(self, adv_adj): """Account must be ledger, active and not freezed""" - ret = sql("""select group_or_ledger, docstatus, freeze_account, company + ret = webnotes.conn.sql("""select group_or_ledger, docstatus, freeze_account, company from tabAccount where name=%s""", self.doc.account, as_dict=1) if ret and ret[0]["group_or_ledger"]=='Group': @@ -145,7 +145,7 @@ class DocType: def update_outstanding_amt(self): # get final outstanding amt - bal = flt(sql("""select sum(debit) - sum(credit) from `tabGL Entry` + bal = flt(webnotes.conn.sql("""select sum(debit) - sum(credit) from `tabGL Entry` where against_voucher=%s and against_voucher_type=%s and account = %s and ifnull(is_cancelled,'No') = 'No'""", (self.doc.against_voucher, self.doc.against_voucher_type, self.doc.account))[0][0] or 0.0) @@ -170,5 +170,5 @@ class DocType: # Update outstanding amt on against voucher if self.doc.against_voucher_type in ["Sales Invoice", "Purchase Invoice"]: - sql("update `tab%s` set outstanding_amount=%s where name='%s'"% + webnotes.conn.sql("update `tab%s` set outstanding_amount=%s where name='%s'"% (self.doc.against_voucher_type, bal, self.doc.against_voucher)) \ No newline at end of file diff --git a/accounts/doctype/mis_control/mis_control.py b/accounts/doctype/mis_control/mis_control.py index bb582704907..f10e3d7df33 100644 --- a/accounts/doctype/mis_control/mis_control.py +++ b/accounts/doctype/mis_control/mis_control.py @@ -43,7 +43,7 @@ class DocType: ret['company'] = get_companies() #--- to get fiscal year and start_date of that fiscal year ----- - res = sql("select name, year_start_date from `tabFiscal Year`") + res = webnotes.conn.sql("select name, year_start_date from `tabFiscal Year`") ret['fiscal_year'] = [r[0] for r in res] ret['start_dates'] = {} for r in res: @@ -51,7 +51,7 @@ class DocType: #--- from month and to month (for MIS - Comparison Report) ------- month_list = ['Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec'] - fiscal_start_month = sql("select MONTH(year_start_date) from `tabFiscal Year` where name = %s",(webnotes.defaults.get_global_default("fiscal_year"))) + fiscal_start_month = webnotes.conn.sql("select MONTH(year_start_date) from `tabFiscal Year` where name = %s",(webnotes.defaults.get_global_default("fiscal_year"))) fiscal_start_month = fiscal_start_month and fiscal_start_month[0][0] or 1 mon = [''] for i in range(fiscal_start_month,13): mon.append(month_list[i-1]) @@ -106,7 +106,7 @@ class DocType: def dates(self,fiscal_year,from_date,to_date): import datetime ret = '' - start_date = cstr(sql("select year_start_date from `tabFiscal Year` where name = %s",fiscal_year)[0][0]) + start_date = cstr(webnotes.conn.sql("select year_start_date from `tabFiscal Year` where name = %s",fiscal_year)[0][0]) st_mon = cint(from_date.split('-')[1]) ed_mon = cint(to_date.split('-')[1]) st_day = cint(from_date.split('-')[2]) @@ -151,7 +151,7 @@ class DocType: def get_totals(self, args): args = eval(args) #msgprint(args) - totals = sql("SELECT %s FROM %s WHERE %s %s %s %s" %(cstr(args['query_val']), cstr(args['tables']), cstr(args['company']), cstr(args['cond']), cstr(args['add_cond']), cstr(args['fil_cond'])), as_dict = 1)[0] + totals = webnotes.conn.sql("SELECT %s FROM %s WHERE %s %s %s %s" %(cstr(args['query_val']), cstr(args['tables']), cstr(args['company']), cstr(args['cond']), cstr(args['add_cond']), cstr(args['fil_cond'])), as_dict = 1)[0] #msgprint(totals) tot_keys = totals.keys() # return in flt because JSON doesn't accept Decimal @@ -184,7 +184,7 @@ class DocType: # Get Children # ------------ def get_children(self, parent_account, level, pl, company, fy): - cl = sql("select distinct account_name, name, debit_or_credit, lft, rgt from `tabAccount` where ifnull(parent_account, '') = %s and ifnull(is_pl_account, 'No')=%s and company=%s and docstatus != 2 order by name asc", (parent_account, pl, company)) + cl = webnotes.conn.sql("select distinct account_name, name, debit_or_credit, lft, rgt from `tabAccount` where ifnull(parent_account, '') = %s and ifnull(is_pl_account, 'No')=%s and company=%s and docstatus != 2 order by name asc", (parent_account, pl, company)) level0_diff = [0 for p in self.period_list] if pl=='Yes' and level==0: # switch for income & expenses cl = [c for c in cl] @@ -237,7 +237,7 @@ class DocType: def define_periods(self, year, period): # get year start date - ysd = sql("select year_start_date from `tabFiscal Year` where name=%s", year) + ysd = webnotes.conn.sql("select year_start_date from `tabFiscal Year` where name=%s", year) ysd = ysd and ysd[0][0] or '' self.ysd = ysd diff --git a/accounts/doctype/period_closing_voucher/period_closing_voucher.py b/accounts/doctype/period_closing_voucher/period_closing_voucher.py index 9df653ad884..237bb638a56 100644 --- a/accounts/doctype/period_closing_voucher/period_closing_voucher.py +++ b/accounts/doctype/period_closing_voucher/period_closing_voucher.py @@ -23,7 +23,7 @@ class DocType: def validate_account_head(self): - acc_det = sql("select debit_or_credit, is_pl_account, group_or_ledger, company \ + acc_det = webnotes.conn.sql("select debit_or_credit, is_pl_account, group_or_ledger, company \ from `tabAccount` where name = '%s'" % (self.doc.closing_account_head)) # Account should be under liability @@ -43,7 +43,7 @@ class DocType: def validate_posting_date(self): - yr = sql("""select year_start_date, adddate(year_start_date, interval 1 year) + yr = webnotes.conn.sql("""select year_start_date, adddate(year_start_date, interval 1 year) from `tabFiscal Year` where name=%s""", (self.doc.fiscal_year, )) self.year_start_date = yr and yr[0][0] or '' self.year_end_date = yr and yr[0][1] or '' @@ -54,7 +54,7 @@ class DocType: raise Exception # Period Closing Entry - pce = sql("select name from `tabPeriod Closing Voucher` \ + pce = webnotes.conn.sql("select name from `tabPeriod Closing Voucher` \ where posting_date > '%s' and fiscal_year = '%s' and docstatus = 1" \ % (self.doc.posting_date, self.doc.fiscal_year)) if pce and pce[0][0]: @@ -64,13 +64,13 @@ class DocType: def validate_pl_balances(self): - income_bal = sql("select sum(ifnull(t1.debit,0))-sum(ifnull(t1.credit,0)) \ + income_bal = webnotes.conn.sql("select sum(ifnull(t1.debit,0))-sum(ifnull(t1.credit,0)) \ from `tabGL Entry` t1, tabAccount t2 where t1.account = t2.name \ and t1.posting_date between '%s' and '%s' and t2.debit_or_credit = 'Credit' \ and t2.group_or_ledger = 'Ledger' and t2.is_pl_account = 'Yes' and t2.docstatus < 2 \ and t2.company = '%s'" % (self.year_start_date, self.doc.posting_date, self.doc.company)) - expense_bal = sql("select sum(ifnull(t1.debit,0))-sum(ifnull(t1.credit,0)) \ + expense_bal = webnotes.conn.sql("select sum(ifnull(t1.debit,0))-sum(ifnull(t1.credit,0)) \ from `tabGL Entry` t1, tabAccount t2 where t1.account = t2.name \ and t1.posting_date between '%s' and '%s' and t2.debit_or_credit = 'Debit' \ and t2.group_or_ledger = 'Ledger' and t2.is_pl_account = 'Yes' and t2.docstatus < 2 \ @@ -86,7 +86,7 @@ class DocType: def get_pl_balances(self, d_or_c): """Get account (pl) specific balance""" - acc_bal = sql("select t1.account, sum(ifnull(t1.debit,0))-sum(ifnull(t1.credit,0)) \ + acc_bal = webnotes.conn.sql("select t1.account, sum(ifnull(t1.debit,0))-sum(ifnull(t1.credit,0)) \ from `tabGL Entry` t1, `tabAccount` t2 where t1.account = t2.name and t2.group_or_ledger = 'Ledger' \ and ifnull(t2.is_pl_account, 'No') = 'Yes' and ifnull(is_cancelled, 'No') = 'No' \ and t2.debit_or_credit = '%s' and t2.docstatus < 2 and t2.company = '%s' \ @@ -169,7 +169,7 @@ class DocType: def on_cancel(self): # get all submit entries of current closing entry voucher - gl_entries = sql("select account, debit, credit from `tabGL Entry` where voucher_type = 'Period Closing Voucher' and voucher_no = '%s' and ifnull(is_cancelled, 'No') = 'No'" % (self.doc.name)) + gl_entries = webnotes.conn.sql("select account, debit, credit from `tabGL Entry` where voucher_type = 'Period Closing Voucher' and voucher_no = '%s' and ifnull(is_cancelled, 'No') = 'No'" % (self.doc.name)) # Swap Debit & Credit Column and make gl entry for gl in gl_entries: @@ -177,4 +177,4 @@ class DocType: self.save_entry(fdict, is_cancel = 'Yes') # Update is_cancelled = 'Yes' to all gl entries for current voucher - sql("update `tabGL Entry` set is_cancelled = 'Yes' where voucher_type = '%s' and voucher_no = '%s'" % (self.doc.doctype, self.doc.name)) \ No newline at end of file + webnotes.conn.sql("update `tabGL Entry` set is_cancelled = 'Yes' where voucher_type = '%s' and voucher_no = '%s'" % (self.doc.doctype, self.doc.name)) \ No newline at end of file diff --git a/accounts/doctype/purchase_invoice/purchase_invoice.py b/accounts/doctype/purchase_invoice/purchase_invoice.py index 0c5a277a0ce..be0e2241284 100644 --- a/accounts/doctype/purchase_invoice/purchase_invoice.py +++ b/accounts/doctype/purchase_invoice/purchase_invoice.py @@ -61,7 +61,7 @@ class DocType(BuyingController): "purchase_receipt_details") def get_credit_to(self): - acc_head = sql("""select name, credit_days from `tabAccount` + acc_head = webnotes.conn.sql("""select name, credit_days from `tabAccount` where (name = %s or (master_name = %s and master_type = 'supplier')) and docstatus != 2 and company = %s""", (cstr(self.doc.supplier) + " - " + self.company_abbr, @@ -88,14 +88,14 @@ class DocType(BuyingController): return get_obj('Purchase Common').get_rate(arg,self) def get_rate1(self,acc): - rate = sql("select tax_rate from `tabAccount` where name='%s'"%(acc)) + rate = webnotes.conn.sql("select tax_rate from `tabAccount` where name='%s'"%(acc)) ret={'add_tax_rate' :rate and flt(rate[0][0]) or 0 } return ret def check_active_purchase_items(self): for d in getlist(self.doclist, 'entries'): if d.item_code: # extra condn coz item_code is not mandatory in PV - valid_item = sql("select docstatus,is_purchase_item from tabItem where name = %s",d.item_code) + valid_item = webnotes.conn.sql("select docstatus,is_purchase_item from tabItem where name = %s",d.item_code) if valid_item[0][0] == 2: msgprint("Item : '%s' is Inactive, you can restore it from Trash" %(d.item_code)) raise Exception @@ -115,7 +115,7 @@ class DocType(BuyingController): def validate_bill_no(self): if self.doc.bill_no and self.doc.bill_no.lower().strip() \ not in ['na', 'not applicable', 'none']: - b_no = sql("""select bill_no, name, ifnull(is_opening,'') from `tabPurchase Invoice` + b_no = webnotes.conn.sql("""select bill_no, name, ifnull(is_opening,'') from `tabPurchase Invoice` where bill_no = %s and credit_to = %s and docstatus = 1 and name != %s""", (self.doc.bill_no, self.doc.credit_to, self.doc.name)) if b_no and cstr(b_no[0][2]) == cstr(self.doc.is_opening): @@ -131,7 +131,7 @@ class DocType(BuyingController): self.doc.remarks = "No Remarks" def validate_credit_acc(self): - acc = sql("select debit_or_credit, is_pl_account from tabAccount where name = %s", + acc = webnotes.conn.sql("select debit_or_credit, is_pl_account from tabAccount where name = %s", self.doc.credit_to) if not acc: msgprint("Account: "+ self.doc.credit_to + "does not exist") @@ -147,7 +147,7 @@ class DocType(BuyingController): # ------------------------------------------------------------ def check_for_acc_head_of_supplier(self): if self.doc.supplier and self.doc.credit_to: - acc_head = sql("select master_name from `tabAccount` where name = %s", self.doc.credit_to) + acc_head = webnotes.conn.sql("select master_name from `tabAccount` where name = %s", self.doc.credit_to) if (acc_head and cstr(acc_head[0][0]) != cstr(self.doc.supplier)) or (not acc_head and (self.doc.credit_to != cstr(self.doc.supplier) + " - " + self.company_abbr)): msgprint("Credit To: %s do not match with Supplier: %s for Company: %s.\n If both correctly entered, please select Master Type and Master Name in account master." %(self.doc.credit_to,self.doc.supplier,self.doc.company), raise_exception=1) @@ -159,7 +159,7 @@ class DocType(BuyingController): for d in getlist(self.doclist,'entries'): if d.purchase_order and not d.purchase_order in check_list and not d.purchase_receipt: check_list.append(d.purhcase_order) - stopped = sql("select name from `tabPurchase Order` where status = 'Stopped' and name = '%s'" % d.purchase_order) + stopped = webnotes.conn.sql("select name from `tabPurchase Order` where status = 'Stopped' and name = '%s'" % d.purchase_order) if stopped: msgprint("One cannot do any transaction against 'Purchase Order' : %s, it's status is 'Stopped'" % (d.purhcase_order)) raise Exception @@ -258,11 +258,11 @@ class DocType(BuyingController): def check_prev_docstatus(self): for d in getlist(self.doclist,'entries'): if d.purchase_order: - submitted = sql("select name from `tabPurchase Order` where docstatus = 1 and name = '%s'" % d.purchase_order) + submitted = webnotes.conn.sql("select name from `tabPurchase Order` where docstatus = 1 and name = '%s'" % d.purchase_order) if not submitted: webnotes.throw("Purchase Order : "+ cstr(d.purchase_order) +" is not submitted") if d.purchase_receipt: - submitted = sql("select name from `tabPurchase Receipt` where docstatus = 1 and name = '%s'" % d.purchase_receipt) + submitted = webnotes.conn.sql("select name from `tabPurchase Receipt` where docstatus = 1 and name = '%s'" % d.purchase_receipt) if not submitted: webnotes.throw("Purchase Receipt : "+ cstr(d.purchase_receipt) +" is not submitted") diff --git a/buying/doctype/purchase_common/purchase_common.py b/buying/doctype/purchase_common/purchase_common.py index dfe2af57f51..c05aba48839 100644 --- a/buying/doctype/purchase_common/purchase_common.py +++ b/buying/doctype/purchase_common/purchase_common.py @@ -22,14 +22,14 @@ class DocType(BuyingController): msgprint(_("You need to put at least one item in the item table."), raise_exception=True) def get_supplier_details(self, name = ''): - details = sql("select supplier_name,address from `tabSupplier` where name = '%s' and docstatus != 2" %(name), as_dict = 1) + details = webnotes.conn.sql("select supplier_name,address from `tabSupplier` where name = '%s' and docstatus != 2" %(name), as_dict = 1) if details: ret = { 'supplier_name' : details and details[0]['supplier_name'] or '', 'supplier_address' : details and details[0]['address'] or '' } # ********** get primary contact details (this is done separately coz. , in case there is no primary contact thn it would not be able to fetch customer details in case of join query) - contact_det = sql("select contact_name, contact_no, email_id from `tabContact` where supplier = '%s' and is_supplier = 1 and is_primary_contact = 'Yes' and docstatus != 2" %(name), as_dict = 1) + contact_det = webnotes.conn.sql("select contact_name, contact_no, email_id from `tabContact` where supplier = '%s' and is_supplier = 1 and is_primary_contact = 'Yes' and docstatus != 2" %(name), as_dict = 1) ret['contact_person'] = contact_det and contact_det[0]['contact_name'] or '' return ret else: @@ -39,7 +39,7 @@ class DocType(BuyingController): # Get Available Qty at Warehouse def get_bin_details( self, arg = ''): arg = eval(arg) - bin = sql("select projected_qty from `tabBin` where item_code = %s and warehouse = %s", (arg['item_code'], arg['warehouse']), as_dict=1) + bin = webnotes.conn.sql("select projected_qty from `tabBin` where item_code = %s and warehouse = %s", (arg['item_code'], arg['warehouse']), as_dict=1) ret = { 'projected_qty' : bin and flt(bin[0]['projected_qty']) or 0 } return ret @@ -69,7 +69,7 @@ class DocType(BuyingController): # update last purchsae rate if last_purchase_rate: - sql("update `tabItem` set last_purchase_rate = %s where name = %s", + webnotes.conn.sql("update `tabItem` set last_purchase_rate = %s where name = %s", (flt(last_purchase_rate),d.item_code)) def get_last_purchase_rate(self, obj): @@ -106,7 +106,7 @@ class DocType(BuyingController): raise Exception # udpate with latest quantities - bin = sql("select projected_qty from `tabBin` where item_code = %s and warehouse = %s", (d.item_code, d.warehouse), as_dict = 1) + bin = webnotes.conn.sql("select projected_qty from `tabBin` where item_code = %s and warehouse = %s", (d.item_code, d.warehouse), as_dict = 1) f_lst ={'projected_qty': bin and flt(bin[0]['projected_qty']) or 0, 'ordered_qty': 0, 'received_qty' : 0} if d.doctype == 'Purchase Receipt Item': @@ -115,7 +115,7 @@ class DocType(BuyingController): if d.fields.has_key(x): d.fields[x] = f_lst[x] - item = sql("select is_stock_item, is_purchase_item, is_sub_contracted_item, end_of_life from tabItem where name=%s", + item = webnotes.conn.sql("select is_stock_item, is_purchase_item, is_sub_contracted_item, end_of_life from tabItem where name=%s", d.item_code) if not item: msgprint("Item %s does not exist in Item Master." % cstr(d.item_code), raise_exception=True) @@ -138,7 +138,7 @@ class DocType(BuyingController): # if is not stock item f = [d.schedule_date, d.item_code, d.description] - ch = sql("select is_stock_item from `tabItem` where name = '%s'"%d.item_code) + ch = webnotes.conn.sql("select is_stock_item from `tabItem` where name = '%s'"%d.item_code) if ch and ch[0][0] == 'Yes': # check for same items @@ -164,18 +164,18 @@ class DocType(BuyingController): # but if in Material Request uom KG it can change in PO get_qty = (transaction == 'Material Request - Purchase Order') and 'qty * conversion_factor' or 'qty' - qty = sql("select sum(%s) from `tab%s` where %s = '%s' and docstatus = 1 and parent != '%s'"% ( get_qty, curr_doctype, ref_tab_fname, ref_tab_dn, curr_parent_name)) + qty = webnotes.conn.sql("select sum(%s) from `tab%s` where %s = '%s' and docstatus = 1 and parent != '%s'"% ( get_qty, curr_doctype, ref_tab_fname, ref_tab_dn, curr_parent_name)) qty = qty and flt(qty[0][0]) or 0 # get total qty of ref doctype #-------------------- - max_qty = sql("select qty from `tab%s` where name = '%s' and docstatus = 1"% (ref_doc_tname, ref_tab_dn)) + max_qty = webnotes.conn.sql("select qty from `tab%s` where name = '%s' and docstatus = 1"% (ref_doc_tname, ref_tab_dn)) max_qty = max_qty and flt(max_qty[0][0]) or 0 return cstr(qty)+'~~~'+cstr(max_qty) def check_for_stopped_status(self, doctype, docname): - stopped = sql("select name from `tab%s` where name = '%s' and status = 'Stopped'" % + stopped = webnotes.conn.sql("select name from `tab%s` where name = '%s' and status = 'Stopped'" % ( doctype, docname)) if stopped: msgprint("One cannot do any transaction against %s : %s, it's status is 'Stopped'" % @@ -183,7 +183,7 @@ class DocType(BuyingController): def check_docstatus(self, check, doctype, docname , detail_doctype = ''): if check == 'Next': - submitted = sql("""select t1.name from `tab%s` t1,`tab%s` t2 + submitted = webnotes.conn.sql("""select t1.name from `tab%s` t1,`tab%s` t2 where t1.name = t2.parent and t2.prevdoc_docname = %s and t1.docstatus = 1""" % (doctype, detail_doctype, '%s'), docname) if submitted: @@ -191,7 +191,7 @@ class DocType(BuyingController): + _(" has already been submitted."), raise_exception=1) if check == 'Previous': - submitted = sql("""select name from `tab%s` + submitted = webnotes.conn.sql("""select name from `tab%s` where docstatus = 1 and name = %s"""% (doctype, '%s'), docname) if not submitted: msgprint(cstr(doctype) + ": " + cstr(submitted[0][0]) @@ -199,7 +199,7 @@ class DocType(BuyingController): def get_rate(self, arg, obj): arg = eval(arg) - rate = sql("select account_type, tax_rate from `tabAccount` where name = %s" + rate = webnotes.conn.sql("select account_type, tax_rate from `tabAccount` where name = %s" , (arg['account_head']), as_dict=1) return {'rate': rate and (rate[0]['account_type'] == 'Tax' \ @@ -208,6 +208,6 @@ class DocType(BuyingController): def get_prevdoc_date(self, obj): for d in getlist(obj.doclist, obj.fname): if d.prevdoc_doctype and d.prevdoc_docname: - dt = sql("select transaction_date from `tab%s` where name = %s" + dt = webnotes.conn.sql("select transaction_date from `tab%s` where name = %s" % (d.prevdoc_doctype, '%s'), (d.prevdoc_docname)) d.prevdoc_date = dt and dt[0][0].strftime('%Y-%m-%d') or '' \ No newline at end of file diff --git a/buying/doctype/purchase_order/purchase_order.py b/buying/doctype/purchase_order/purchase_order.py index 951ff8b70e7..c41b9dfef88 100644 --- a/buying/doctype/purchase_order/purchase_order.py +++ b/buying/doctype/purchase_order/purchase_order.py @@ -130,8 +130,8 @@ class DocType(BuyingController): get_obj("Warehouse", d.warehouse).update_bin(args) def check_modified_date(self): - mod_db = sql("select modified from `tabPurchase Order` where name = '%s'" % self.doc.name) - date_diff = sql("select TIMEDIFF('%s', '%s')" % ( mod_db[0][0],cstr(self.doc.modified))) + mod_db = webnotes.conn.sql("select modified from `tabPurchase Order` where name = '%s'" % self.doc.name) + date_diff = webnotes.conn.sql("select TIMEDIFF('%s', '%s')" % ( mod_db[0][0],cstr(self.doc.modified))) if date_diff and date_diff[0][0]: msgprint(cstr(self.doc.doctype) +" => "+ cstr(self.doc.name) +" has been modified. Please Refresh. ") @@ -170,7 +170,7 @@ class DocType(BuyingController): pc_obj.check_docstatus(check = 'Next', doctype = 'Purchase Receipt', docname = self.doc.name, detail_doctype = 'Purchase Receipt Item') # Check if Purchase Invoice has been submitted against current Purchase Order - submitted = sql("select t1.name from `tabPurchase Invoice` t1,`tabPurchase Invoice Item` t2 where t1.name = t2.parent and t2.purchase_order = '%s' and t1.docstatus = 1" % self.doc.name) + submitted = webnotes.conn.sql("select t1.name from `tabPurchase Invoice` t1,`tabPurchase Invoice Item` t2 where t1.name = t2.parent and t2.purchase_order = '%s' and t1.docstatus = 1" % self.doc.name) if submitted: msgprint("Purchase Invoice : " + cstr(submitted[0][0]) + " has already been submitted !") raise Exception diff --git a/buying/doctype/supplier/supplier.py b/buying/doctype/supplier/supplier.py index 2c1d173ea72..3c0163367be 100644 --- a/buying/doctype/supplier/supplier.py +++ b/buying/doctype/supplier/supplier.py @@ -28,7 +28,7 @@ class DocType(TransactionBase): self.doc.name = make_autoname(self.doc.naming_series + '.#####') def update_credit_days_limit(self): - sql("""update tabAccount set credit_days = %s where name = %s""", + webnotes.conn.sql("""update tabAccount set credit_days = %s where name = %s""", (cint(self.doc.credit_days), self.doc.name + " - " + self.get_company_abbr())) def on_update(self): @@ -42,7 +42,7 @@ class DocType(TransactionBase): self.update_credit_days_limit() def get_payables_group(self): - g = sql("select payables_group from tabCompany where name=%s", self.doc.company) + g = webnotes.conn.sql("select payables_group from tabCompany where name=%s", self.doc.company) g = g and g[0][0] or '' if not g: msgprint("Update Company master, assign a default group for Payables") @@ -64,14 +64,14 @@ class DocType(TransactionBase): msgprint(_("Created Group ") + ac) def get_company_abbr(self): - return sql("select abbr from tabCompany where name=%s", self.doc.company)[0][0] + return webnotes.conn.sql("select abbr from tabCompany where name=%s", self.doc.company)[0][0] def get_parent_account(self, abbr): if (not self.doc.supplier_type): msgprint("Supplier Type is mandatory") raise Exception - if not sql("select name from tabAccount where name=%s and debit_or_credit = 'Credit' and ifnull(is_pl_account, 'No') = 'No'", (self.doc.supplier_type + " - " + abbr)): + if not webnotes.conn.sql("select name from tabAccount where name=%s and debit_or_credit = 'Credit' and ifnull(is_pl_account, 'No') = 'No'", (self.doc.supplier_type + " - " + abbr)): # if not group created , create it self.add_account(self.doc.supplier_type, self.get_payables_group(), abbr) @@ -89,7 +89,7 @@ class DocType(TransactionBase): abbr = self.get_company_abbr() parent_account = self.get_parent_account(abbr) - if not sql("select name from tabAccount where name=%s", (self.doc.name + " - " + abbr)): + if not webnotes.conn.sql("select name from tabAccount where name=%s", (self.doc.name + " - " + abbr)): ac_bean = webnotes.bean({ "doctype": "Account", 'account_name': self.doc.name, @@ -120,15 +120,15 @@ class DocType(TransactionBase): def get_contacts(self,nm): if nm: - contact_details =webnotes.conn.convert_to_lists(sql("select name, CONCAT(IFNULL(first_name,''),' ',IFNULL(last_name,'')),contact_no,email_id from `tabContact` where supplier = '%s'"%nm)) + contact_details =webnotes.conn.convert_to_lists(webnotes.conn.sql("select name, CONCAT(IFNULL(first_name,''),' ',IFNULL(last_name,'')),contact_no,email_id from `tabContact` where supplier = '%s'"%nm)) return contact_details else: return '' def delete_supplier_address(self): - for rec in sql("select * from `tabAddress` where supplier=%s", (self.doc.name,), as_dict=1): - sql("delete from `tabAddress` where name=%s",(rec['name'])) + for rec in webnotes.conn.sql("select * from `tabAddress` where supplier=%s", (self.doc.name,), as_dict=1): + webnotes.conn.sql("delete from `tabAddress` where name=%s",(rec['name'])) def delete_supplier_contact(self): for contact in webnotes.conn.sql_list("""select name from `tabContact` @@ -137,7 +137,7 @@ class DocType(TransactionBase): def delete_supplier_account(self): """delete supplier's ledger if exist and check balance before deletion""" - acc = sql("select name from `tabAccount` where master_type = 'Supplier' \ + acc = webnotes.conn.sql("select name from `tabAccount` where master_type = 'Supplier' \ and master_name = %s and docstatus < 2", self.doc.name) if acc: from webnotes.model import delete_doc @@ -160,7 +160,7 @@ class DocType(TransactionBase): ('Purchase Receipt', 'supplier'), ('Serial No', 'supplier')] for rec in update_fields: - sql("update `tab%s` set supplier_name = %s where `%s` = %s" % \ + webnotes.conn.sql("update `tab%s` set supplier_name = %s where `%s` = %s" % \ (rec[0], '%s', rec[1], '%s'), (new, old)) for account in webnotes.conn.sql("""select name, account_name from diff --git a/hr/doctype/attendance/attendance.py b/hr/doctype/attendance/attendance.py index 124d3621a5a..6d52b5723d9 100644 --- a/hr/doctype/attendance/attendance.py +++ b/hr/doctype/attendance/attendance.py @@ -14,7 +14,7 @@ class DocType: self.doclist = doclist def validate_duplicate_record(self): - res = sql("""select name from `tabAttendance` where employee = %s and att_date = %s + res = webnotes.conn.sql("""select name from `tabAttendance` where employee = %s and att_date = %s and name != %s and docstatus = 1""", (self.doc.employee, self.doc.att_date, self.doc.name)) if res: @@ -23,7 +23,7 @@ class DocType: def check_leave_record(self): if self.doc.status == 'Present': - leave = sql("""select name from `tabLeave Application` + leave = webnotes.conn.sql("""select name from `tabLeave Application` where employee = %s and %s between from_date and to_date and status = 'Approved' and docstatus = 1""", (self.doc.employee, self.doc.att_date)) @@ -41,7 +41,7 @@ class DocType: msgprint(_("Attendance can not be marked for future dates"), raise_exception=1) def validate_employee(self): - emp = sql("select name from `tabEmployee` where name = %s and status = 'Active'", + emp = webnotes.conn.sql("select name from `tabEmployee` where name = %s and status = 'Active'", self.doc.employee) if not emp: msgprint(_("Employee: ") + self.doc.employee + diff --git a/hr/doctype/leave_allocation/leave_allocation.py b/hr/doctype/leave_allocation/leave_allocation.py index 8e226908d8b..a058e1db778 100755 --- a/hr/doctype/leave_allocation/leave_allocation.py +++ b/hr/doctype/leave_allocation/leave_allocation.py @@ -36,7 +36,7 @@ class DocType: def check_existing_leave_allocation(self): """check whether leave for same type is already allocated or not""" - leave_allocation = sql("""select name from `tabLeave Allocation` + leave_allocation = webnotes.conn.sql("""select name from `tabLeave Allocation` where employee=%s and leave_type=%s and fiscal_year=%s and docstatus=1""", (self.doc.employee, self.doc.leave_type, self.doc.fiscal_year)) if leave_allocation: @@ -63,14 +63,14 @@ class DocType: return self.get_leaves_allocated(prev_fyear) - self.get_leaves_applied(prev_fyear) def get_leaves_applied(self, fiscal_year): - leaves_applied = sql("""select SUM(ifnull(total_leave_days, 0)) + leaves_applied = webnotes.conn.sql("""select SUM(ifnull(total_leave_days, 0)) from `tabLeave Application` where employee=%s and leave_type=%s and fiscal_year=%s and docstatus=1""", (self.doc.employee, self.doc.leave_type, fiscal_year)) return leaves_applied and flt(leaves_applied[0][0]) or 0 def get_leaves_allocated(self, fiscal_year): - leaves_allocated = sql("""select SUM(ifnull(total_leaves_allocated, 0)) + leaves_allocated = webnotes.conn.sql("""select SUM(ifnull(total_leaves_allocated, 0)) from `tabLeave Allocation` where employee=%s and leave_type=%s and fiscal_year=%s and docstatus=1 and name!=%s""", (self.doc.employee, self.doc.leave_type, fiscal_year, self.doc.name)) @@ -78,7 +78,7 @@ class DocType: def allow_carry_forward(self): """check whether carry forward is allowed or not for this leave type""" - cf = sql("""select is_carry_forward from `tabLeave Type` where name = %s""", + cf = webnotes.conn.sql("""select is_carry_forward from `tabLeave Type` where name = %s""", self.doc.leave_type) cf = cf and cint(cf[0][0]) or 0 if not cf: @@ -109,7 +109,7 @@ class DocType: webnotes.conn.set(self.doc,'total_leaves_allocated',flt(leave_det['total_leaves_allocated'])) def check_for_leave_application(self): - exists = sql("""select name from `tabLeave Application` + exists = webnotes.conn.sql("""select name from `tabLeave Application` where employee=%s and leave_type=%s and fiscal_year=%s and docstatus=1""", (self.doc.employee, self.doc.leave_type, self.doc.fiscal_year)) if exists: diff --git a/hr/doctype/leave_control_panel/leave_control_panel.py b/hr/doctype/leave_control_panel/leave_control_panel.py index 640432109f1..294701c004b 100644 --- a/hr/doctype/leave_control_panel/leave_control_panel.py +++ b/hr/doctype/leave_control_panel/leave_control_panel.py @@ -33,7 +33,7 @@ class DocType: emp_query = "select name from `tabEmployee` " if flag == 1: emp_query += condition - e = sql(emp_query) + e = webnotes.conn.sql(emp_query) return e # ---------------- diff --git a/hr/doctype/salary_manager/salary_manager.py b/hr/doctype/salary_manager/salary_manager.py index ecc829f87ab..48dcab18084 100644 --- a/hr/doctype/salary_manager/salary_manager.py +++ b/hr/doctype/salary_manager/salary_manager.py @@ -29,7 +29,7 @@ class DocType: cond = self.get_filter_condition() cond += self.get_joining_releiving_condition() - emp_list = sql(""" + emp_list = webnotes.conn.sql(""" select t1.name from `tabEmployee` t1, `tabSalary Structure` t2 where t1.docstatus!=2 and t2.docstatus != 2 @@ -67,7 +67,7 @@ class DocType: def get_month_details(self, year, month): - ysd = sql("select year_start_date from `tabFiscal Year` where name ='%s'"%year)[0][0] + ysd = webnotes.conn.sql("select year_start_date from `tabFiscal Year` where name ='%s'"%year)[0][0] if ysd: from dateutil.relativedelta import relativedelta import calendar, datetime @@ -95,7 +95,7 @@ class DocType: emp_list = self.get_emp_list() ss_list = [] for emp in emp_list: - if not sql("""select name from `tabSalary Slip` + if not webnotes.conn.sql("""select name from `tabSalary Slip` where docstatus!= 2 and employee = %s and month = %s and fiscal_year = %s and company = %s """, (emp[0], self.doc.month, self.doc.fiscal_year, self.doc.company)): ss = webnotes.bean({ @@ -126,7 +126,7 @@ class DocType: which are not submitted """ cond = self.get_filter_condition() - ss_list = sql(""" + ss_list = webnotes.conn.sql(""" select t1.name from `tabSalary Slip` t1 where t1.docstatus = 0 and month = '%s' and fiscal_year = '%s' %s """ % (self.doc.month, self.doc.fiscal_year, cond)) @@ -188,7 +188,7 @@ class DocType: Get total salary amount from submitted salary slip based on selected criteria """ cond = self.get_filter_condition() - tot = sql(""" + tot = webnotes.conn.sql(""" select sum(rounded_total) from `tabSalary Slip` t1 where t1.docstatus = 1 and month = '%s' and fiscal_year = '%s' %s """ % (self.doc.month, self.doc.fiscal_year, cond)) @@ -201,7 +201,7 @@ class DocType: get default bank account,default salary acount from company """ amt = self.get_total_salary() - com = sql("select default_bank_account from `tabCompany` where name = '%s'" % self.doc.company) + com = webnotes.conn.sql("select default_bank_account from `tabCompany` where name = '%s'" % self.doc.company) if not com[0][0] or not com[0][1]: msgprint("You can set Default Bank Account in Company master.") diff --git a/hr/doctype/salary_manager/test_salary_manager.py b/hr/doctype/salary_manager/test_salary_manager.py index 04000f06701..13815db52be 100644 --- a/hr/doctype/salary_manager/test_salary_manager.py +++ b/hr/doctype/salary_manager/test_salary_manager.py @@ -9,7 +9,7 @@ test_records = [] # from webnotes.model.doc import Document # from webnotes.model.code import get_obj -# sql = webnotes.conn.sql +# webnotes.conn.sql = webnotes.conn.sql # # class TestSalaryManager(unittest.TestCase): # def setUp(self): @@ -20,15 +20,15 @@ test_records = [] # ss1[0].employee = emp1.name # for s in ss1: s.save(1) # for s in ss1[1:]: -# sql("update `tabSalary Structure Earning` set parent = '%s' where name = '%s'" % (ss1[0].name, s.name)) -# sql("update `tabSalary Structure Deduction` set parent = '%s' where name = '%s'" % (ss1[0].name, s.name)) +# webnotes.conn.sql("update `tabSalary Structure Earning` set parent = '%s' where name = '%s'" % (ss1[0].name, s.name)) +# webnotes.conn.sql("update `tabSalary Structure Deduction` set parent = '%s' where name = '%s'" % (ss1[0].name, s.name)) # # # ss2[0].employee = emp2.name # for s in ss2: s.save(1) # for s in ss2[1:]: -# sql("update `tabSalary Structure Earning` set parent = '%s' where name = '%s'" % (ss2[0].name, s.name)) -# sql("update `tabSalary Structure Deduction` set parent = '%s' where name = '%s'" % (ss2[0].name, s.name)) +# webnotes.conn.sql("update `tabSalary Structure Earning` set parent = '%s' where name = '%s'" % (ss2[0].name, s.name)) +# webnotes.conn.sql("update `tabSalary Structure Deduction` set parent = '%s' where name = '%s'" % (ss2[0].name, s.name)) # # sman.save() # self.sm = get_obj('Salary Manager') @@ -36,7 +36,7 @@ test_records = [] # self.sm.create_sal_slip() # # def test_creation(self): -# ssid = sql(""" +# ssid = webnotes.conn.sql(""" # select name, department # from `tabSalary Slip` # where month = '08' and fiscal_year='2011-2012'""") @@ -46,7 +46,7 @@ test_records = [] # # # def test_lwp_calc(self): -# ss = sql(""" +# ss = webnotes.conn.sql(""" # select payment_days # from `tabSalary Slip` # where month = '08' and fiscal_year='2011-2012' and employee = '%s' diff --git a/hr/doctype/salary_slip/salary_slip.py b/hr/doctype/salary_slip/salary_slip.py index 71042731704..dab026e3645 100644 --- a/hr/doctype/salary_slip/salary_slip.py +++ b/hr/doctype/salary_slip/salary_slip.py @@ -31,7 +31,7 @@ class DocType(TransactionBase): def check_sal_struct(self): - struct = sql("select name from `tabSalary Structure` where employee ='%s' and is_active = 'Yes' "%self.doc.employee) + struct = webnotes.conn.sql("select name from `tabSalary Structure` where employee ='%s' and is_active = 'Yes' "%self.doc.employee) if not struct: msgprint("Please create Salary Structure for employee '%s'"%self.doc.employee) self.doc.employee = '' @@ -99,13 +99,13 @@ class DocType(TransactionBase): return payment_days def get_holidays_for_employee(self, m): - holidays = sql("""select t1.holiday_date + holidays = webnotes.conn.sql("""select t1.holiday_date from `tabHoliday` t1, tabEmployee t2 where t1.parent = t2.holiday_list and t2.name = %s and t1.holiday_date between %s and %s""", (self.doc.employee, m['month_start_date'], m['month_end_date'])) if not holidays: - holidays = sql("""select t1.holiday_date + holidays = webnotes.conn.sql("""select t1.holiday_date from `tabHoliday` t1, `tabHoliday List` t2 where t1.parent = t2.name and ifnull(t2.is_default, 0) = 1 and t2.fiscal_year = %s @@ -119,7 +119,7 @@ class DocType(TransactionBase): for d in range(m['month_days']): dt = add_days(cstr(m['month_start_date']), d) if dt not in holidays: - leave = sql(""" + leave = webnotes.conn.sql(""" select t1.name, t1.half_day from `tabLeave Application` t1, `tabLeave Type` t2 where t2.name = t1.leave_type @@ -133,7 +133,7 @@ class DocType(TransactionBase): return lwp def check_existing(self): - ret_exist = sql("""select name from `tabSalary Slip` + ret_exist = webnotes.conn.sql("""select name from `tabSalary Slip` where month = %s and fiscal_year = %s and docstatus != 2 and employee = %s and name != %s""", (self.doc.month, self.doc.fiscal_year, self.doc.employee, self.doc.name)) @@ -200,9 +200,9 @@ class DocType(TransactionBase): receiver = webnotes.conn.get_value("Employee", self.doc.employee, "company_email") if receiver: subj = 'Salary Slip - ' + cstr(self.doc.month) +'/'+cstr(self.doc.fiscal_year) - earn_ret=sql("""select e_type, e_modified_amount from `tabSalary Slip Earning` + earn_ret=webnotes.conn.sql("""select e_type, e_modified_amount from `tabSalary Slip Earning` where parent = %s""", self.doc.name) - ded_ret=sql("""select d_type, d_modified_amount from `tabSalary Slip Deduction` + ded_ret=webnotes.conn.sql("""select d_type, d_modified_amount from `tabSalary Slip Deduction` where parent = %s""", self.doc.name) earn_table = '' diff --git a/hr/doctype/salary_structure/salary_structure.py b/hr/doctype/salary_structure/salary_structure.py index c3cd93d48c6..bfa7850d51d 100644 --- a/hr/doctype/salary_structure/salary_structure.py +++ b/hr/doctype/salary_structure/salary_structure.py @@ -19,7 +19,7 @@ class DocType: def get_employee_details(self): ret = {} - det = sql("""select employee_name, branch, designation, department, grade + det = webnotes.conn.sql("""select employee_name, branch, designation, department, grade from `tabEmployee` where name = %s""", self.doc.employee) if det: ret = { @@ -33,7 +33,7 @@ class DocType: return ret def get_ss_values(self,employee): - basic_info = sql("""select bank_name, bank_ac_no, esic_card_no, pf_number + basic_info = webnotes.conn.sql("""select bank_name, bank_ac_no, esic_card_no, pf_number from `tabEmployee` where name =%s""", employee) ret = {'bank_name': basic_info and basic_info[0][0] or '', 'bank_ac_no': basic_info and basic_info[0][1] or '', @@ -42,7 +42,7 @@ class DocType: return ret def make_table(self, doct_name, tab_fname, tab_name): - list1 = sql("select name from `tab%s` where docstatus != 2" % doct_name) + list1 = webnotes.conn.sql("select name from `tab%s` where docstatus != 2" % doct_name) for li in list1: child = addchild(self.doc, tab_fname, tab_name, self.doclist) if(tab_fname == 'earning_details'): @@ -57,7 +57,7 @@ class DocType: self.make_table('Deduction Type','deduction_details', 'Salary Structure Deduction') def check_existing(self): - ret = sql("""select name from `tabSalary Structure` where is_active = 'Yes' + ret = webnotes.conn.sql("""select name from `tabSalary Structure` where is_active = 'Yes' and employee = %s and name!=%s""", (self.doc.employee,self.doc.name)) if ret and self.doc.is_active=='Yes': msgprint(_("""Another Salary Structure '%s' is active for employee '%s'. diff --git a/manufacturing/doctype/bom/bom.py b/manufacturing/doctype/bom/bom.py index 84a3d6c13b9..20c11410930 100644 --- a/manufacturing/doctype/bom/bom.py +++ b/manufacturing/doctype/bom/bom.py @@ -17,7 +17,7 @@ class DocType: self.doclist = doclist def autoname(self): - last_name = sql("""select max(name) from `tabBOM` + last_name = webnotes.conn.sql("""select max(name) from `tabBOM` where name like "BOM/%s/%%" """ % cstr(self.doc.item).replace('"', '\\"')) if last_name: idx = cint(cstr(last_name[0][0]).split('/')[-1].split('-')[0]) + 1 @@ -143,7 +143,7 @@ class DocType: webnotes.bean(self.doclist).update_after_submit() def get_bom_unitcost(self, bom_no): - bom = sql("""select name, total_cost/quantity as unit_cost from `tabBOM` + bom = webnotes.conn.sql("""select name, total_cost/quantity as unit_cost from `tabBOM` where is_active = 1 and name = %s""", bom_no, as_dict=1) return bom and bom[0]['unit_cost'] or 0 @@ -155,7 +155,7 @@ class DocType: from stock.utils import get_incoming_rate dt = self.doc.costing_date or nowdate() time = self.doc.costing_date == nowdate() and now().split()[1] or '23:59' - warehouse = sql("select warehouse from `tabBin` where item_code = %s", args['item_code']) + warehouse = webnotes.conn.sql("select warehouse from `tabBin` where item_code = %s", args['item_code']) rate = [] for wh in warehouse: r = get_incoming_rate({ @@ -183,7 +183,7 @@ class DocType: if not self.doc.is_active: webnotes.conn.set(self.doc, "is_default", 0) - sql("update `tabItem` set default_bom = null where name = %s and default_bom = %s", + webnotes.conn.sql("update `tabItem` set default_bom = null where name = %s and default_bom = %s", (self.doc.item, self.doc.name)) def clear_operations(self): @@ -249,7 +249,7 @@ class DocType: def validate_bom_no(self, item, bom_no, idx): """Validate BOM No of sub-contracted items""" - bom = sql("""select name from `tabBOM` where name = %s and item = %s + bom = webnotes.conn.sql("""select name from `tabBOM` where name = %s and item = %s and is_active=1 and docstatus=1""", (bom_no, item), as_dict =1) if not bom: @@ -271,7 +271,7 @@ class DocType: for d in check_list: bom_list, count = [self.doc.name], 0 while (len(bom_list) > count ): - boms = sql(" select %s from `tabBOM Item` where %s = '%s' " % + boms = webnotes.conn.sql(" select %s from `tabBOM Item` where %s = '%s' " % (d[0], d[1], cstr(bom_list[count]))) count = count + 1 for b in boms: @@ -363,7 +363,7 @@ class DocType: def get_child_exploded_items(self, bom_no, qty): """ Add all items from Flat BOM of child BOM""" - child_fb_items = sql("""select item_code, description, stock_uom, qty, rate, + child_fb_items = webnotes.conn.sql("""select item_code, description, stock_uom, qty, rate, qty_consumed_per_unit from `tabBOM Explosion Item` where parent = %s and docstatus = 1""", bom_no, as_dict = 1) @@ -389,12 +389,12 @@ class DocType: ch.save(1) def get_parent_bom_list(self, bom_no): - p_bom = sql("select parent from `tabBOM Item` where bom_no = '%s'" % bom_no) + p_bom = webnotes.conn.sql("select parent from `tabBOM Item` where bom_no = '%s'" % bom_no) return p_bom and [i[0] for i in p_bom] or [] def validate_bom_links(self): if not self.doc.is_active: - act_pbom = sql("""select distinct bom_item.parent from `tabBOM Item` bom_item + act_pbom = webnotes.conn.sql("""select distinct bom_item.parent from `tabBOM Item` bom_item where bom_item.bom_no = %s and bom_item.docstatus = 1 and exists (select * from `tabBOM` where name = bom_item.parent and docstatus = 1 and is_active = 1)""", self.doc.name) diff --git a/manufacturing/doctype/production_order/production_order.py b/manufacturing/doctype/production_order/production_order.py index 28adc65e36c..b9d15fdf962 100644 --- a/manufacturing/doctype/production_order/production_order.py +++ b/manufacturing/doctype/production_order/production_order.py @@ -22,14 +22,14 @@ class DocType: "In Process", "Completed", "Cancelled"]) if self.doc.production_item : - item_detail = sql("select name from `tabItem` where name = '%s' and docstatus != 2" + item_detail = webnotes.conn.sql("select name from `tabItem` where name = '%s' and docstatus != 2" % self.doc.production_item, as_dict = 1) if not item_detail: msgprint("Item '%s' does not exist or cancelled in the system." % cstr(self.doc.production_item), raise_exception=1) if self.doc.bom_no: - bom = sql("""select name from `tabBOM` where name=%s and docstatus=1 + bom = webnotes.conn.sql("""select name from `tabBOM` where name=%s and docstatus=1 and is_active=1 and item=%s""" , (self.doc.bom_no, self.doc.production_item), as_dict =1) if not bom: @@ -103,7 +103,7 @@ class DocType: def on_cancel(self): # Check whether any stock entry exists against this Production Order - stock_entry = sql("""select name from `tabStock Entry` + stock_entry = webnotes.conn.sql("""select name from `tabStock Entry` where production_order = %s and docstatus = 1""", self.doc.name) if stock_entry: msgprint("""Submitted Stock Entry %s exists against this production order. diff --git a/manufacturing/doctype/production_planning_tool/production_planning_tool.py b/manufacturing/doctype/production_planning_tool/production_planning_tool.py index c150be3ff69..5480f177d92 100644 --- a/manufacturing/doctype/production_planning_tool/production_planning_tool.py +++ b/manufacturing/doctype/production_planning_tool/production_planning_tool.py @@ -18,7 +18,7 @@ class DocType: def get_so_details(self, so): """Pull other details from so""" - so = sql("""select transaction_date, customer, grand_total + so = webnotes.conn.sql("""select transaction_date, customer, grand_total from `tabSales Order` where name = %s""", so, as_dict = 1) ret = { 'sales_order_date': so and so[0]['transaction_date'] or '', @@ -30,7 +30,7 @@ class DocType: def get_item_details(self, item_code): """ Pull other item details from item master""" - item = sql("""select description, stock_uom, default_bom + item = webnotes.conn.sql("""select description, stock_uom, default_bom from `tabItem` where name = %s""", item_code, as_dict =1) ret = { 'description' : item and item[0]['description'], @@ -62,7 +62,7 @@ class DocType: if self.doc.fg_item: item_filter += ' and item.name = "' + self.doc.fg_item + '"' - open_so = sql(""" + open_so = webnotes.conn.sql(""" select distinct so.name, so.transaction_date, so.customer, so.grand_total from `tabSales Order` so, `tabSales Order Item` so_item where so_item.parent = so.name @@ -107,7 +107,7 @@ class DocType: msgprint("Please enter sales order in the above table") return [] - items = sql("""select distinct parent, item_code, reserved_warehouse, + items = webnotes.conn.sql("""select distinct parent, item_code, reserved_warehouse, (qty - ifnull(delivered_qty, 0)) as pending_qty from `tabSales Order Item` so_item where parent in (%s) and docstatus = 1 and ifnull(qty, 0) > ifnull(delivered_qty, 0) @@ -116,7 +116,7 @@ class DocType: or ifnull(item.is_sub_contracted_item, 'No') = 'Yes'))""" % \ (", ".join(["%s"] * len(so_list))), tuple(so_list), as_dict=1) - dnpi_items = sql("""select distinct dnpi.parent, dnpi.item_code, dnpi.warehouse as reserved_warhouse, + dnpi_items = webnotes.conn.sql("""select distinct dnpi.parent, dnpi.item_code, dnpi.warehouse as reserved_warhouse, (((so_item.qty - ifnull(so_item.delivered_qty, 0)) * dnpi.qty) / so_item.qty) as pending_qty from `tabSales Order Item` so_item, `tabDelivery Note Packing Item` dnpi @@ -135,7 +135,7 @@ class DocType: self.clear_item_table() for p in items: - item_details = sql("""select description, stock_uom, default_bom + item_details = webnotes.conn.sql("""select description, stock_uom, default_bom from tabItem where name=%s""", p['item_code']) pi = addchild(self.doc, 'pp_details', 'Production Plan Item', self.doclist) pi.sales_order = p['parent'] @@ -161,7 +161,7 @@ class DocType: msgprint("Please enter bom no for item: %s at row no: %s" % (d.item_code, d.idx), raise_exception=1) else: - bom = sql("""select name from `tabBOM` where name = %s and item = %s + bom = webnotes.conn.sql("""select name from `tabBOM` where name = %s and item = %s and docstatus = 1 and is_active = 1""", (d.bom_no, d.item_code), as_dict = 1) if not bom: @@ -242,7 +242,7 @@ class DocType: for bom in bom_dict: if self.doc.use_multi_level_bom: # get all raw materials with sub assembly childs - fl_bom_items = sql("""select fb.item_code, + fl_bom_items = webnotes.conn.sql("""select fb.item_code, ifnull(sum(fb.qty_consumed_per_unit), 0)*%s as qty, fb.description, fb.stock_uom, it.min_order_qty from `tabBOM Explosion Item` fb,`tabItem` it @@ -253,7 +253,7 @@ class DocType: else: # Get all raw materials considering SA items as raw materials, # so no childs of SA items - fl_bom_items = sql("""select bom_item.item_code, + fl_bom_items = webnotes.conn.sql("""select bom_item.item_code, ifnull(sum(bom_item.qty_consumed_per_unit), 0) * %s, bom_item.description, bom_item.stock_uom, item.min_order_qty from `tabBOM Item` bom_item, tabItem item @@ -273,7 +273,7 @@ class DocType: 'Quantity Requested for Purchase', 'Ordered Qty', 'Actual Qty']] for d in self.item_dict: item_list.append([d, self.item_dict[d][1], self.item_dict[d][2], self.item_dict[d][0]]) - item_qty= sql("""select warehouse, indented_qty, ordered_qty, actual_qty + item_qty= webnotes.conn.sql("""select warehouse, indented_qty, ordered_qty, actual_qty from `tabBin` where item_code = %s""", d) i_qty, o_qty, a_qty = 0, 0, 0 for w in item_qty: diff --git a/manufacturing/doctype/workstation/workstation.py b/manufacturing/doctype/workstation/workstation.py index 56833a9e5b0..cc129340e4a 100644 --- a/manufacturing/doctype/workstation/workstation.py +++ b/manufacturing/doctype/workstation/workstation.py @@ -17,9 +17,9 @@ class DocType: self.doclist = doclist def update_bom_operation(self): - bom_list = sql(" select DISTINCT parent from `tabBOM Operation` where workstation = '%s'" % self.doc.name) + bom_list = webnotes.conn.sql(" select DISTINCT parent from `tabBOM Operation` where workstation = '%s'" % self.doc.name) for bom_no in bom_list: - sql("update `tabBOM Operation` set hour_rate = '%s' where parent = '%s' and workstation = '%s'"%( self.doc.hour_rate, bom_no[0], self.doc.name)) + webnotes.conn.sql("update `tabBOM Operation` set hour_rate = '%s' where parent = '%s' and workstation = '%s'"%( self.doc.hour_rate, bom_no[0], self.doc.name)) def on_update(self): webnotes.conn.set(self.doc, 'overhead', flt(self.doc.hour_rate_electricity) + flt(self.doc.hour_rate_consumable) + flt(self.doc.hour_rate_rent)) diff --git a/projects/doctype/task/task.py b/projects/doctype/task/task.py index 856be5cc889..fb9b6ab6a67 100644 --- a/projects/doctype/task/task.py +++ b/projects/doctype/task/task.py @@ -16,13 +16,13 @@ class DocType: self.doclist = doclist def get_project_details(self): - cust = sql("select customer, customer_name from `tabProject` where name = %s", self.doc.project) + cust = webnotes.conn.sql("select customer, customer_name from `tabProject` where name = %s", self.doc.project) if cust: ret = {'customer': cust and cust[0][0] or '', 'customer_name': cust and cust[0][1] or ''} return ret def get_customer_details(self): - cust = sql("select customer_name from `tabCustomer` where name=%s", self.doc.customer) + cust = webnotes.conn.sql("select customer_name from `tabCustomer` where name=%s", self.doc.customer) if cust: ret = {'customer_name': cust and cust[0][0] or ''} return ret diff --git a/selling/doctype/customer/customer.py b/selling/doctype/customer/customer.py index 0c2bf616ddd..78fad0034fb 100644 --- a/selling/doctype/customer/customer.py +++ b/selling/doctype/customer/customer.py @@ -30,7 +30,7 @@ class DocType(TransactionBase): return webnotes.conn.get_value('Company', self.doc.company, 'abbr') def get_receivables_group(self): - g = sql("select receivables_group from tabCompany where name=%s", self.doc.company) + g = webnotes.conn.sql("select receivables_group from tabCompany where name=%s", self.doc.company) g = g and g[0][0] or '' if not g: msgprint("Update Company master, assign a default group for Receivables") @@ -46,7 +46,7 @@ class DocType(TransactionBase): def update_lead_status(self): if self.doc.lead_name: - sql("update `tabLead` set status='Converted' where name = %s", self.doc.lead_name) + webnotes.conn.sql("update `tabLead` set status='Converted' where name = %s", self.doc.lead_name) def create_account_head(self): if self.doc.company : @@ -131,7 +131,7 @@ class DocType(TransactionBase): def delete_customer_account(self): """delete customer's ledger if exist and check balance before deletion""" - acc = sql("select name from `tabAccount` where master_type = 'Customer' \ + acc = webnotes.conn.sql("select name from `tabAccount` where master_type = 'Customer' \ and master_name = %s and docstatus < 2", self.doc.name) if acc: from webnotes.model import delete_doc @@ -142,7 +142,7 @@ class DocType(TransactionBase): self.delete_customer_contact() self.delete_customer_account() if self.doc.lead_name: - sql("update `tabLead` set status='Interested' where name=%s",self.doc.lead_name) + webnotes.conn.sql("update `tabLead` set status='Interested' where name=%s",self.doc.lead_name) def on_rename(self, new, old, merge=False): #update customer_name if not naming series diff --git a/selling/doctype/lead/lead.py b/selling/doctype/lead/lead.py index c0ef242baa8..eb3c69571a3 100644 --- a/selling/doctype/lead/lead.py +++ b/selling/doctype/lead/lead.py @@ -37,7 +37,7 @@ class DocType(SellingController): webnotes.conn.set(self.doc, 'status', status) def check_status(self): - chk = sql("select status from `tabLead` where name=%s", self.doc.name) + chk = webnotes.conn.sql("select status from `tabLead` where name=%s", self.doc.name) chk = chk and chk[0][0] or '' return cstr(chk) diff --git a/selling/doctype/opportunity/opportunity.py b/selling/doctype/opportunity/opportunity.py index df6861a7731..284c5e0545c 100644 --- a/selling/doctype/opportunity/opportunity.py +++ b/selling/doctype/opportunity/opportunity.py @@ -26,7 +26,7 @@ class DocType(TransactionBase): }) def get_item_details(self, item_code): - item = sql("""select item_name, stock_uom, description_html, description, item_group, brand + item = webnotes.conn.sql("""select item_name, stock_uom, description_html, description, item_group, brand from `tabItem` where name = %s""", item_code, as_dict=1) ret = { 'item_name': item and item[0]['item_name'] or '', @@ -38,7 +38,7 @@ class DocType(TransactionBase): return ret def get_cust_address(self,name): - details = sql("select customer_name, address, territory, customer_group from `tabCustomer` where name = '%s' and docstatus != 2" %(name), as_dict = 1) + details = webnotes.conn.sql("select customer_name, address, territory, customer_group from `tabCustomer` where name = '%s' and docstatus != 2" %(name), as_dict = 1) if details: ret = { 'customer_name': details and details[0]['customer_name'] or '', @@ -48,7 +48,7 @@ class DocType(TransactionBase): } # ********** get primary contact details (this is done separately coz. , in case there is no primary contact thn it would not be able to fetch customer details in case of join query) - contact_det = sql("select contact_name, contact_no, email_id from `tabContact` where customer = '%s' and is_customer = 1 and is_primary_contact = 'Yes' and docstatus != 2" %(name), as_dict = 1) + contact_det = webnotes.conn.sql("select contact_name, contact_no, email_id from `tabContact` where customer = '%s' and is_customer = 1 and is_primary_contact = 'Yes' and docstatus != 2" %(name), as_dict = 1) ret['contact_person'] = contact_det and contact_det[0]['contact_name'] or '' ret['contact_no'] = contact_det and contact_det[0]['contact_no'] or '' @@ -61,7 +61,7 @@ class DocType(TransactionBase): def get_contact_details(self, arg): arg = eval(arg) - contact = sql("select contact_no, email_id from `tabContact` where contact_name = '%s' and customer_name = '%s'" %(arg['contact_person'],arg['customer']), as_dict = 1) + contact = webnotes.conn.sql("select contact_no, email_id from `tabContact` where contact_name = '%s' and customer_name = '%s'" %(arg['contact_person'],arg['customer']), as_dict = 1) ret = { 'contact_no' : contact and contact[0]['contact_no'] or '', 'email_id' : contact and contact[0]['email_id'] or '' @@ -135,7 +135,7 @@ class DocType(TransactionBase): webnotes.conn.set(self.doc, 'status', 'Submitted') def on_cancel(self): - chk = sql("select t1.name from `tabQuotation` t1, `tabQuotation Item` t2 where t2.parent = t1.name and t1.docstatus=1 and (t1.status!='Order Lost' and t1.status!='Cancelled') and t2.prevdoc_docname = %s",self.doc.name) + chk = webnotes.conn.sql("select t1.name from `tabQuotation` t1, `tabQuotation Item` t2 where t2.parent = t1.name and t1.docstatus=1 and (t1.status!='Order Lost' and t1.status!='Cancelled') and t2.prevdoc_docname = %s",self.doc.name) if chk: msgprint("Quotation No. "+cstr(chk[0][0])+" is submitted against this Opportunity. Thus can not be cancelled.") raise Exception @@ -143,7 +143,7 @@ class DocType(TransactionBase): webnotes.conn.set(self.doc, 'status', 'Cancelled') def declare_enquiry_lost(self,arg): - chk = sql("select t1.name from `tabQuotation` t1, `tabQuotation Item` t2 where t2.parent = t1.name and t1.docstatus=1 and (t1.status!='Order Lost' and t1.status!='Cancelled') and t2.prevdoc_docname = %s",self.doc.name) + chk = webnotes.conn.sql("select t1.name from `tabQuotation` t1, `tabQuotation Item` t2 where t2.parent = t1.name and t1.docstatus=1 and (t1.status!='Order Lost' and t1.status!='Cancelled') and t2.prevdoc_docname = %s",self.doc.name) if chk: msgprint("Quotation No. "+cstr(chk[0][0])+" is submitted against this Opportunity. Thus 'Opportunity Lost' can not be declared against it.") raise Exception diff --git a/selling/doctype/quotation/quotation.py b/selling/doctype/quotation/quotation.py index 8ac0d1925ad..8a3bef10e9f 100644 --- a/selling/doctype/quotation/quotation.py +++ b/selling/doctype/quotation/quotation.py @@ -77,7 +77,7 @@ class DocType(SellingController): if self.doc.order_type in ['Maintenance', 'Service']: for d in getlist(self.doclist, 'quotation_details'): - is_service_item = sql("select is_service_item from `tabItem` where name=%s", d.item_code) + is_service_item = webnotes.conn.sql("select is_service_item from `tabItem` where name=%s", d.item_code) is_service_item = is_service_item and is_service_item[0][0] or 'No' if is_service_item == 'No': @@ -85,7 +85,7 @@ class DocType(SellingController): raise Exception else: for d in getlist(self.doclist, 'quotation_details'): - is_sales_item = sql("select is_sales_item from `tabItem` where name=%s", d.item_code) + is_sales_item = webnotes.conn.sql("select is_sales_item from `tabItem` where name=%s", d.item_code) is_sales_item = is_sales_item and is_sales_item[0][0] or 'No' if is_sales_item == 'No': @@ -141,18 +141,18 @@ class DocType(SellingController): if prevdoc: if flag == 'submit': #on submit - sql("update `tabOpportunity` set status = 'Quotation Sent' where name = %s", prevdoc) + webnotes.conn.sql("update `tabOpportunity` set status = 'Quotation Sent' where name = %s", prevdoc) elif flag == 'cancel': #on cancel - sql("update `tabOpportunity` set status = 'Open' where name = %s", prevdoc) + webnotes.conn.sql("update `tabOpportunity` set status = 'Open' where name = %s", prevdoc) elif flag == 'order lost': #order lost - sql("update `tabOpportunity` set status = 'Opportunity Lost' where name=%s", prevdoc) + webnotes.conn.sql("update `tabOpportunity` set status = 'Opportunity Lost' where name=%s", prevdoc) elif flag == 'order confirm': #order confirm - sql("update `tabOpportunity` set status='Order Confirmed' where name=%s", prevdoc) + webnotes.conn.sql("update `tabOpportunity` set status='Order Confirmed' where name=%s", prevdoc) # declare as order lost #------------------------- def declare_order_lost(self, arg): - chk = sql("select t1.name from `tabSales Order` t1, `tabSales Order Item` t2 where t2.parent = t1.name and t1.docstatus=1 and t2.prevdoc_docname = %s",self.doc.name) + chk = webnotes.conn.sql("select t1.name from `tabSales Order` t1, `tabSales Order Item` t2 where t2.parent = t1.name and t1.docstatus=1 and t2.prevdoc_docname = %s",self.doc.name) if chk: msgprint("Sales Order No. "+cstr(chk[0][0])+" is submitted against this Quotation. Thus 'Order Lost' can not be declared against it.") raise Exception diff --git a/selling/doctype/sales_order/sales_order.py b/selling/doctype/sales_order/sales_order.py index 5043a77d76c..c9ef5d3bbab 100644 --- a/selling/doctype/sales_order/sales_order.py +++ b/selling/doctype/sales_order/sales_order.py @@ -87,14 +87,14 @@ class DocType(SellingController): # used for production plan d.transaction_date = self.doc.transaction_date - tot_avail_qty = sql("select projected_qty from `tabBin` \ + tot_avail_qty = webnotes.conn.sql("select projected_qty from `tabBin` \ where item_code = '%s' and warehouse = '%s'" % (d.item_code,d.reserved_warehouse)) d.projected_qty = tot_avail_qty and flt(tot_avail_qty[0][0]) or 0 def validate_sales_mntc_quotation(self): for d in getlist(self.doclist, 'sales_order_details'): if d.prevdoc_docname: - res = sql("select name from `tabQuotation` where name=%s and order_type = %s", (d.prevdoc_docname, self.doc.order_type)) + res = webnotes.conn.sql("select name from `tabQuotation` where name=%s and order_type = %s", (d.prevdoc_docname, self.doc.order_type)) if not res: msgprint("""Order Type (%s) should be same in Quotation: %s \ and current Sales Order""" % (self.doc.order_type, d.prevdoc_docname)) @@ -111,7 +111,7 @@ class DocType(SellingController): def validate_proj_cust(self): if self.doc.project_name and self.doc.customer_name: - res = sql("select name from `tabProject` where name = '%s' and (customer = '%s' or ifnull(customer,'')='')"%(self.doc.project_name, self.doc.customer)) + res = webnotes.conn.sql("select name from `tabProject` where name = '%s' and (customer = '%s' or ifnull(customer,'')='')"%(self.doc.project_name, self.doc.customer)) if not res: msgprint("Customer - %s does not belong to project - %s. \n\nIf you want to use project for multiple customers then please make customer details blank in project - %s."%(self.doc.customer,self.doc.project_name,self.doc.project_name)) raise Exception @@ -167,28 +167,28 @@ class DocType(SellingController): def check_prev_docstatus(self): for d in getlist(self.doclist, 'sales_order_details'): - cancel_quo = sql("select name from `tabQuotation` where docstatus = 2 and name = '%s'" % d.prevdoc_docname) + cancel_quo = webnotes.conn.sql("select name from `tabQuotation` where docstatus = 2 and name = '%s'" % d.prevdoc_docname) if cancel_quo: msgprint("Quotation :" + cstr(cancel_quo[0][0]) + " is already cancelled !") raise Exception , "Validation Error. " def update_enquiry_status(self, prevdoc, flag): - enq = sql("select t2.prevdoc_docname from `tabQuotation` t1, `tabQuotation Item` t2 where t2.parent = t1.name and t1.name=%s", prevdoc) + enq = webnotes.conn.sql("select t2.prevdoc_docname from `tabQuotation` t1, `tabQuotation Item` t2 where t2.parent = t1.name and t1.name=%s", prevdoc) if enq: - sql("update `tabOpportunity` set status = %s where name=%s",(flag,enq[0][0])) + webnotes.conn.sql("update `tabOpportunity` set status = %s where name=%s",(flag,enq[0][0])) def update_prevdoc_status(self, flag): for d in getlist(self.doclist, 'sales_order_details'): if d.prevdoc_docname: if flag=='submit': - sql("update `tabQuotation` set status = 'Order Confirmed' where name=%s",d.prevdoc_docname) + webnotes.conn.sql("update `tabQuotation` set status = 'Order Confirmed' where name=%s",d.prevdoc_docname) #update enquiry self.update_enquiry_status(d.prevdoc_docname, 'Order Confirmed') elif flag == 'cancel': - chk = sql("select t1.name from `tabSales Order` t1, `tabSales Order Item` t2 where t2.parent = t1.name and t2.prevdoc_docname=%s and t1.name!=%s and t1.docstatus=1", (d.prevdoc_docname,self.doc.name)) + chk = webnotes.conn.sql("select t1.name from `tabSales Order` t1, `tabSales Order Item` t2 where t2.parent = t1.name and t2.prevdoc_docname=%s and t1.name!=%s and t1.docstatus=1", (d.prevdoc_docname,self.doc.name)) if not chk: - sql("update `tabQuotation` set status = 'Submitted' where name=%s",d.prevdoc_docname) + webnotes.conn.sql("update `tabQuotation` set status = 'Submitted' where name=%s",d.prevdoc_docname) #update enquiry self.update_enquiry_status(d.prevdoc_docname, 'Quotation Sent') @@ -218,35 +218,35 @@ class DocType(SellingController): def check_nextdoc_docstatus(self): # Checks Delivery Note - submit_dn = sql("select t1.name from `tabDelivery Note` t1,`tabDelivery Note Item` t2 where t1.name = t2.parent and t2.prevdoc_docname = '%s' and t1.docstatus = 1" % (self.doc.name)) + submit_dn = webnotes.conn.sql("select t1.name from `tabDelivery Note` t1,`tabDelivery Note Item` t2 where t1.name = t2.parent and t2.prevdoc_docname = '%s' and t1.docstatus = 1" % (self.doc.name)) if submit_dn: msgprint("Delivery Note : " + cstr(submit_dn[0][0]) + " has been submitted against " + cstr(self.doc.doctype) + ". Please cancel Delivery Note : " + cstr(submit_dn[0][0]) + " first and then cancel "+ cstr(self.doc.doctype), raise_exception = 1) # Checks Sales Invoice - submit_rv = sql("select t1.name from `tabSales Invoice` t1,`tabSales Invoice Item` t2 where t1.name = t2.parent and t2.sales_order = '%s' and t1.docstatus = 1" % (self.doc.name)) + submit_rv = webnotes.conn.sql("select t1.name from `tabSales Invoice` t1,`tabSales Invoice Item` t2 where t1.name = t2.parent and t2.sales_order = '%s' and t1.docstatus = 1" % (self.doc.name)) if submit_rv: msgprint("Sales Invoice : " + cstr(submit_rv[0][0]) + " has already been submitted against " +cstr(self.doc.doctype)+ ". Please cancel Sales Invoice : "+ cstr(submit_rv[0][0]) + " first and then cancel "+ cstr(self.doc.doctype), raise_exception = 1) #check maintenance schedule - submit_ms = sql("select t1.name from `tabMaintenance Schedule` t1, `tabMaintenance Schedule Item` t2 where t2.parent=t1.name and t2.prevdoc_docname = %s and t1.docstatus = 1",self.doc.name) + submit_ms = webnotes.conn.sql("select t1.name from `tabMaintenance Schedule` t1, `tabMaintenance Schedule Item` t2 where t2.parent=t1.name and t2.prevdoc_docname = %s and t1.docstatus = 1",self.doc.name) if submit_ms: msgprint("Maintenance Schedule : " + cstr(submit_ms[0][0]) + " has already been submitted against " +cstr(self.doc.doctype)+ ". Please cancel Maintenance Schedule : "+ cstr(submit_ms[0][0]) + " first and then cancel "+ cstr(self.doc.doctype), raise_exception = 1) # check maintenance visit - submit_mv = sql("select t1.name from `tabMaintenance Visit` t1, `tabMaintenance Visit Purpose` t2 where t2.parent=t1.name and t2.prevdoc_docname = %s and t1.docstatus = 1",self.doc.name) + submit_mv = webnotes.conn.sql("select t1.name from `tabMaintenance Visit` t1, `tabMaintenance Visit Purpose` t2 where t2.parent=t1.name and t2.prevdoc_docname = %s and t1.docstatus = 1",self.doc.name) if submit_mv: msgprint("Maintenance Visit : " + cstr(submit_mv[0][0]) + " has already been submitted against " +cstr(self.doc.doctype)+ ". Please cancel Maintenance Visit : " + cstr(submit_mv[0][0]) + " first and then cancel "+ cstr(self.doc.doctype), raise_exception = 1) # check production order - pro_order = sql("""select name from `tabProduction Order` where sales_order = %s and docstatus = 1""", self.doc.name) + pro_order = webnotes.conn.sql("""select name from `tabProduction Order` where sales_order = %s and docstatus = 1""", self.doc.name) if pro_order: msgprint("""Production Order: %s exists against this sales order. Please cancel production order first and then cancel this sales order""" % pro_order[0][0], raise_exception=1) def check_modified_date(self): - mod_db = sql("select modified from `tabSales Order` where name = '%s'" % self.doc.name) - date_diff = sql("select TIMEDIFF('%s', '%s')" % ( mod_db[0][0],cstr(self.doc.modified))) + mod_db = webnotes.conn.sql("select modified from `tabSales Order` where name = '%s'" % self.doc.name) + date_diff = webnotes.conn.sql("select TIMEDIFF('%s', '%s')" % ( mod_db[0][0],cstr(self.doc.modified))) if date_diff and date_diff[0][0]: msgprint("%s: %s has been modified after you have opened. Please Refresh" % (self.doc.doctype, self.doc.name), raise_exception=1) diff --git a/selling/doctype/sms_center/sms_center.py b/selling/doctype/sms_center/sms_center.py index 8db20b0275a..6f16798d8b7 100644 --- a/selling/doctype/sms_center/sms_center.py +++ b/selling/doctype/sms_center/sms_center.py @@ -28,15 +28,15 @@ class DocType: where_clause = self.doc.sales_partner and " and ifnull(is_sales_partner, 0) = 1 and sales_partner = '%s'" % self.doc.sales_partner or " and ifnull(sales_partner, '') != ''" if self.doc.send_to in ['All Contact', 'All Customer Contact', 'All Supplier Contact', 'All Sales Partner Contact']: - rec = sql("select CONCAT(ifnull(first_name,''),'',ifnull(last_name,'')), mobile_no from `tabContact` where ifnull(mobile_no,'')!='' and docstatus != 2 %s" % where_clause) + rec = webnotes.conn.sql("select CONCAT(ifnull(first_name,''),'',ifnull(last_name,'')), mobile_no from `tabContact` where ifnull(mobile_no,'')!='' and docstatus != 2 %s" % where_clause) elif self.doc.send_to == 'All Lead (Open)': - rec = sql("select lead_name, mobile_no from tabLead where ifnull(mobile_no,'')!='' and docstatus != 2 and status = 'Open'") + rec = webnotes.conn.sql("select lead_name, mobile_no from tabLead where ifnull(mobile_no,'')!='' and docstatus != 2 and status = 'Open'") elif self.doc.send_to == 'All Employee (Active)': where_clause = self.doc.department and " and department = '%s'" % self.doc.department or "" where_clause += self.doc.branch and " and branch = '%s'" % self.doc.branch or "" - rec = sql("select employee_name, cell_number from `tabEmployee` where status = 'Active' and docstatus < 2 and ifnull(cell_number,'')!='' %s" % where_clause) + rec = webnotes.conn.sql("select employee_name, cell_number from `tabEmployee` where status = 'Active' and docstatus < 2 and ifnull(cell_number,'')!='' %s" % where_clause) elif self.doc.send_to == 'All Sales Person': - rec = sql("select sales_person_name, mobile_no from `tabSales Person` where docstatus != 2 and ifnull(mobile_no,'')!=''") + rec = webnotes.conn.sql("select sales_person_name, mobile_no from `tabSales Person` where docstatus != 2 and ifnull(mobile_no,'')!=''") rec_list = '' for d in rec: rec_list += d[0] + ' - ' + d[1] + '\n' diff --git a/setup/doctype/authorization_control/authorization_control.py b/setup/doctype/authorization_control/authorization_control.py index 26f7705af3e..533f3988e32 100644 --- a/setup/doctype/authorization_control/authorization_control.py +++ b/setup/doctype/authorization_control/authorization_control.py @@ -27,10 +27,10 @@ class DocType(TransactionBase): amt_list.append(flt(x[0])) max_amount = max(amt_list) - app_dtl = sql("select approving_user, approving_role from `tabAuthorization Rule` where transaction = %s and (value = %s or value > %s) and docstatus != 2 and based_on = %s and company = %s %s" % ('%s', '%s', '%s', '%s', '%s', condition), (doctype_name, flt(max_amount), total, based_on, company)) + app_dtl = webnotes.conn.sql("select approving_user, approving_role from `tabAuthorization Rule` where transaction = %s and (value = %s or value > %s) and docstatus != 2 and based_on = %s and company = %s %s" % ('%s', '%s', '%s', '%s', '%s', condition), (doctype_name, flt(max_amount), total, based_on, company)) if not app_dtl: - app_dtl = sql("select approving_user, approving_role from `tabAuthorization Rule` where transaction = %s and (value = %s or value > %s) and docstatus != 2 and based_on = %s and ifnull(company,'') = '' %s" % ('%s', '%s', '%s', '%s', condition), (doctype_name, flt(max_amount), total, based_on)) + app_dtl = webnotes.conn.sql("select approving_user, approving_role from `tabAuthorization Rule` where transaction = %s and (value = %s or value > %s) and docstatus != 2 and based_on = %s and ifnull(company,'') = '' %s" % ('%s', '%s', '%s', '%s', condition), (doctype_name, flt(max_amount), total, based_on)) for d in app_dtl: if(d[0]): appr_users.append(d[0]) if(d[1]): appr_roles.append(d[1]) @@ -57,18 +57,18 @@ class DocType(TransactionBase): add_cond1,add_cond2 = '','' if based_on == 'Itemwise Discount': add_cond1 += " and master_name = '"+cstr(item)+"'" - itemwise_exists = sql("select value from `tabAuthorization Rule` where transaction = %s and value <= %s and based_on = %s and company = %s and docstatus != 2 %s %s" % ('%s', '%s', '%s', '%s', cond, add_cond1), (doctype_name, total, based_on, company)) + itemwise_exists = webnotes.conn.sql("select value from `tabAuthorization Rule` where transaction = %s and value <= %s and based_on = %s and company = %s and docstatus != 2 %s %s" % ('%s', '%s', '%s', '%s', cond, add_cond1), (doctype_name, total, based_on, company)) if not itemwise_exists: - itemwise_exists = sql("select value from `tabAuthorization Rule` where transaction = %s and value <= %s and based_on = %s and ifnull(company,'') = '' and docstatus != 2 %s %s" % ('%s', '%s', '%s', cond, add_cond1), (doctype_name, total, based_on)) + itemwise_exists = webnotes.conn.sql("select value from `tabAuthorization Rule` where transaction = %s and value <= %s and based_on = %s and ifnull(company,'') = '' and docstatus != 2 %s %s" % ('%s', '%s', '%s', cond, add_cond1), (doctype_name, total, based_on)) if itemwise_exists: self.get_appr_user_role(itemwise_exists, doctype_name, total, based_on, cond+add_cond1, item,company) chk = 0 if chk == 1: if based_on == 'Itemwise Discount': add_cond2 += " and ifnull(master_name,'') = ''" - appr = sql("select value from `tabAuthorization Rule` where transaction = %s and value <= %s and based_on = %s and company = %s and docstatus != 2 %s %s" % ('%s', '%s', '%s', '%s', cond, add_cond2), (doctype_name, total, based_on, company)) + appr = webnotes.conn.sql("select value from `tabAuthorization Rule` where transaction = %s and value <= %s and based_on = %s and company = %s and docstatus != 2 %s %s" % ('%s', '%s', '%s', '%s', cond, add_cond2), (doctype_name, total, based_on, company)) if not appr: - appr = sql("select value from `tabAuthorization Rule` where transaction = %s and value <= %s and based_on = %s and ifnull(company,'') = '' and docstatus != 2 %s %s"% ('%s', '%s', '%s', cond, add_cond2), (doctype_name, total, based_on)) + appr = webnotes.conn.sql("select value from `tabAuthorization Rule` where transaction = %s and value <= %s and based_on = %s and ifnull(company,'') = '' and docstatus != 2 %s %s"% ('%s', '%s', '%s', cond, add_cond2), (doctype_name, total, based_on)) self.get_appr_user_role(appr, doctype_name, total, based_on, cond+add_cond2, item, company) @@ -111,7 +111,7 @@ class DocType(TransactionBase): # ================ # Check for authorization set for individual user - based_on = [x[0] for x in sql("select distinct based_on from `tabAuthorization Rule` where transaction = %s and system_user = %s and (company = %s or ifnull(company,'')='') and docstatus != 2", (doctype_name, session['user'], company))] + based_on = [x[0] for x in webnotes.conn.sql("select distinct based_on from `tabAuthorization Rule` where transaction = %s and system_user = %s and (company = %s or ifnull(company,'')='') and docstatus != 2", (doctype_name, session['user'], company))] for d in based_on: self.bifurcate_based_on_type(doctype_name, total, av_dis, d, doc_obj, 1, company) @@ -123,7 +123,7 @@ class DocType(TransactionBase): # Specific Role # =============== # Check for authorization set on particular roles - based_on = [x[0] for x in sql("""select based_on + based_on = [x[0] for x in webnotes.conn.sql("""select based_on from `tabAuthorization Rule` where transaction = %s and system_role IN (%s) and based_on IN (%s) and (company = %s or ifnull(company,'')='') @@ -147,9 +147,9 @@ class DocType(TransactionBase): # payroll related check def get_value_based_rule(self,doctype_name,employee,total_claimed_amount,company): val_lst =[] - val = sql("select value from `tabAuthorization Rule` where transaction=%s and (to_emp=%s or to_designation IN (select designation from `tabEmployee` where name=%s)) and ifnull(value,0)< %s and company = %s and docstatus!=2",(doctype_name,employee,employee,total_claimed_amount,company)) + val = webnotes.conn.sql("select value from `tabAuthorization Rule` where transaction=%s and (to_emp=%s or to_designation IN (select designation from `tabEmployee` where name=%s)) and ifnull(value,0)< %s and company = %s and docstatus!=2",(doctype_name,employee,employee,total_claimed_amount,company)) if not val: - val = sql("select value from `tabAuthorization Rule` where transaction=%s and (to_emp=%s or to_designation IN (select designation from `tabEmployee` where name=%s)) and ifnull(value,0)< %s and ifnull(company,'') = '' and docstatus!=2",(doctype_name, employee, employee, total_claimed_amount)) + val = webnotes.conn.sql("select value from `tabAuthorization Rule` where transaction=%s and (to_emp=%s or to_designation IN (select designation from `tabEmployee` where name=%s)) and ifnull(value,0)< %s and ifnull(company,'') = '' and docstatus!=2",(doctype_name, employee, employee, total_claimed_amount)) if val: val_lst = [y[0] for y in val] @@ -157,9 +157,9 @@ class DocType(TransactionBase): val_lst.append(0) max_val = max(val_lst) - rule = sql("select name, to_emp, to_designation, approving_role, approving_user from `tabAuthorization Rule` where transaction=%s and company = %s and (to_emp=%s or to_designation IN (select designation from `tabEmployee` where name=%s)) and ifnull(value,0)= %s and docstatus!=2",(doctype_name,company,employee,employee,flt(max_val)), as_dict=1) + rule = webnotes.conn.sql("select name, to_emp, to_designation, approving_role, approving_user from `tabAuthorization Rule` where transaction=%s and company = %s and (to_emp=%s or to_designation IN (select designation from `tabEmployee` where name=%s)) and ifnull(value,0)= %s and docstatus!=2",(doctype_name,company,employee,employee,flt(max_val)), as_dict=1) if not rule: - rule = sql("select name, to_emp, to_designation, approving_role, approving_user from `tabAuthorization Rule` where transaction=%s and ifnull(company,'') = '' and (to_emp=%s or to_designation IN (select designation from `tabEmployee` where name=%s)) and ifnull(value,0)= %s and docstatus!=2",(doctype_name,employee,employee,flt(max_val)), as_dict=1) + rule = webnotes.conn.sql("select name, to_emp, to_designation, approving_role, approving_user from `tabAuthorization Rule` where transaction=%s and ifnull(company,'') = '' and (to_emp=%s or to_designation IN (select designation from `tabEmployee` where name=%s)) and ifnull(value,0)= %s and docstatus!=2",(doctype_name,employee,employee,flt(max_val)), as_dict=1) return rule @@ -174,9 +174,9 @@ class DocType(TransactionBase): if doctype_name == 'Expense Claim': rule = self.get_value_based_rule(doctype_name,doc_obj.doc.employee,doc_obj.doc.total_claimed_amount, doc_obj.doc.company) elif doctype_name == 'Appraisal': - rule = sql("select name, to_emp, to_designation, approving_role, approving_user from `tabAuthorization Rule` where transaction=%s and (to_emp=%s or to_designation IN (select designation from `tabEmployee` where name=%s)) and company = %s and docstatus!=2",(doctype_name,doc_obj.doc.employee, doc_obj.doc.employee, doc_obj.doc.company),as_dict=1) + rule = webnotes.conn.sql("select name, to_emp, to_designation, approving_role, approving_user from `tabAuthorization Rule` where transaction=%s and (to_emp=%s or to_designation IN (select designation from `tabEmployee` where name=%s)) and company = %s and docstatus!=2",(doctype_name,doc_obj.doc.employee, doc_obj.doc.employee, doc_obj.doc.company),as_dict=1) if not rule: - rule = sql("select name, to_emp, to_designation, approving_role, approving_user from `tabAuthorization Rule` where transaction=%s and (to_emp=%s or to_designation IN (select designation from `tabEmployee` where name=%s)) and ifnull(company,'') = '' and docstatus!=2",(doctype_name,doc_obj.doc.employee, doc_obj.doc.employee),as_dict=1) + rule = webnotes.conn.sql("select name, to_emp, to_designation, approving_role, approving_user from `tabAuthorization Rule` where transaction=%s and (to_emp=%s or to_designation IN (select designation from `tabEmployee` where name=%s)) and ifnull(company,'') = '' and docstatus!=2",(doctype_name,doc_obj.doc.employee, doc_obj.doc.employee),as_dict=1) if rule: for m in rule: @@ -184,7 +184,7 @@ class DocType(TransactionBase): if m['approving_user']: app_specific_user.append(m['approving_user']) elif m['approving_role']: - user_lst = [z[0] for z in sql("select distinct t1.name from `tabProfile` t1, `tabUserRole` t2 where t2.role=%s and t2.parent=t1.name and t1.name !='Administrator' and t1.name != 'Guest' and t1.docstatus !=2",m['approving_role'])] + user_lst = [z[0] for z in webnotes.conn.sql("select distinct t1.name from `tabProfile` t1, `tabUserRole` t2 where t2.role=%s and t2.parent=t1.name and t1.name !='Administrator' and t1.name != 'Guest' and t1.docstatus !=2",m['approving_role'])] for x in user_lst: if not x in app_user: app_user.append(x) diff --git a/setup/doctype/authorization_rule/authorization_rule.py b/setup/doctype/authorization_rule/authorization_rule.py index 5192ebf769f..ea22b154b91 100644 --- a/setup/doctype/authorization_rule/authorization_rule.py +++ b/setup/doctype/authorization_rule/authorization_rule.py @@ -18,7 +18,7 @@ class DocType: def check_duplicate_entry(self): - exists = sql("""select name, docstatus from `tabAuthorization Rule` + exists = webnotes.conn.sql("""select name, docstatus from `tabAuthorization Rule` where transaction = %s and based_on = %s and system_user = %s and system_role = %s and approving_user = %s and approving_role = %s and to_emp =%s and to_designation=%s and name != %s""", @@ -38,12 +38,12 @@ class DocType: def validate_master_name(self): if self.doc.based_on == 'Customerwise Discount' and \ - not sql("select name from tabCustomer where name = '%s' and docstatus != 2" % \ + not webnotes.conn.sql("select name from tabCustomer where name = '%s' and docstatus != 2" % \ (self.doc.master_name)): msgprint("Please select valid Customer Name for Customerwise Discount", raise_exception=1) elif self.doc.based_on == 'Itemwise Discount' and \ - not sql("select name from tabItem where name = '%s' and docstatus != 2" % \ + not webnotes.conn.sql("select name from tabItem where name = '%s' and docstatus != 2" % \ (self.doc.master_name)): msgprint("Please select valid Item Name for Itemwise Discount", raise_exception=1) elif (self.doc.based_on == 'Grand Total' or \ @@ -64,7 +64,7 @@ class DocType: Applicable To (Role).", raise_exception=1) elif self.doc.system_user and self.doc.approving_role and \ has_common([self.doc.approving_role], [x[0] for x in \ - sql("select role from `tabUserRole` where parent = '%s'" % \ + webnotes.conn.sql("select role from `tabUserRole` where parent = '%s'" % \ (self.doc.system_user))]): msgprint("System User : %s is assigned role : %s. So rule does not make sense" % (self.doc.system_user,self.doc.approving_role), raise_exception=1) diff --git a/setup/doctype/customer_group/customer_group.py b/setup/doctype/customer_group/customer_group.py index 8b68cc50e48..1264c1b3ece 100644 --- a/setup/doctype/customer_group/customer_group.py +++ b/setup/doctype/customer_group/customer_group.py @@ -14,7 +14,7 @@ class DocType(DocTypeNestedSet): self.nsm_parent_field = 'parent_customer_group'; def validate(self): - if sql("select name from `tabCustomer Group` where name = %s and docstatus = 2", + if webnotes.conn.sql("select name from `tabCustomer Group` where name = %s and docstatus = 2", (self.doc.customer_group_name)): msgprint("""Another %s record is trashed. To untrash please go to Setup -> Recycle Bin.""" % @@ -32,7 +32,7 @@ class DocType(DocTypeNestedSet): self.doc.name, raise_exception=1) def on_trash(self): - cust = sql("select name from `tabCustomer` where ifnull(customer_group, '') = %s", + cust = webnotes.conn.sql("select name from `tabCustomer` where ifnull(customer_group, '') = %s", self.doc.name) cust = [d[0] for d in cust] if cust: @@ -41,7 +41,7 @@ class DocType(DocTypeNestedSet): To trash/delete this, remove/change customer group in customer master""" % (self.doc.name, cust or ''), raise_exception=1) - if sql("select name from `tabCustomer Group` where parent_customer_group = %s \ + if webnotes.conn.sql("select name from `tabCustomer Group` where parent_customer_group = %s \ and docstatus != 2", self.doc.name): msgprint("Child customer group exists for this customer group. \ You can not trash/cancel/delete this customer group.", raise_exception=1) diff --git a/setup/doctype/naming_series/naming_series.py b/setup/doctype/naming_series/naming_series.py index 6312801fe8a..4e85b15f6d9 100644 --- a/setup/doctype/naming_series/naming_series.py +++ b/setup/doctype/naming_series/naming_series.py @@ -22,7 +22,7 @@ class DocType: where fieldname='naming_series'""") )))), "prefixes": "\n".join([''] + [i[0] for i in - sql("""select name from tabSeries""")]) + webnotes.conn.sql("""select name from tabSeries""")]) } def scrub_options_list(self, ol): @@ -125,12 +125,12 @@ class DocType: def insert_series(self, series): """insert series if missing""" if not webnotes.conn.exists('Series', series): - sql("insert into tabSeries (name, current) values (%s,0)", (series)) + webnotes.conn.sql("insert into tabSeries (name, current) values (%s,0)", (series)) def update_series_start(self): if self.doc.prefix: self.insert_series(self.doc.prefix) - sql("update `tabSeries` set current = '%s' where name = '%s'" % (self.doc.current_value,self.doc.prefix)) + webnotes.conn.sql("update `tabSeries` set current = '%s' where name = '%s'" % (self.doc.current_value,self.doc.prefix)) msgprint("Series Updated Successfully") else: msgprint("Please select prefix first") diff --git a/setup/doctype/notification_control/notification_control.py b/setup/doctype/notification_control/notification_control.py index 23493624dd4..0a151152d6e 100644 --- a/setup/doctype/notification_control/notification_control.py +++ b/setup/doctype/notification_control/notification_control.py @@ -13,7 +13,7 @@ class DocType: def get_message(self, arg): fn = arg.lower().replace(' ', '_') + '_message' - v = sql("select value from tabSingles where field=%s and doctype=%s", (fn, 'Notification Control')) + v = webnotes.conn.sql("select value from tabSingles where field=%s and doctype=%s", (fn, 'Notification Control')) return v and v[0][0] or '' def set_message(self, arg = ''): diff --git a/setup/doctype/sales_partner/sales_partner.py b/setup/doctype/sales_partner/sales_partner.py index 8915ff1cc0f..79a59db71a3 100644 --- a/setup/doctype/sales_partner/sales_partner.py +++ b/setup/doctype/sales_partner/sales_partner.py @@ -23,7 +23,7 @@ class DocType: def get_contacts(self,nm): if nm: - contact_details =webnotes.conn.convert_to_lists(sql("select name, CONCAT(IFNULL(first_name,''),' ',IFNULL(last_name,'')),contact_no,email_id from `tabContact` where sales_partner = '%s'"%nm)) + contact_details =webnotes.conn.convert_to_lists(webnotes.conn.sql("select name, CONCAT(IFNULL(first_name,''),' ',IFNULL(last_name,'')),contact_no,email_id from `tabContact` where sales_partner = '%s'"%nm)) return contact_details else: return '' diff --git a/stock/doctype/bin/bin.py b/stock/doctype/bin/bin.py index 954ef783a4f..8c892c13244 100644 --- a/stock/doctype/bin/bin.py +++ b/stock/doctype/bin/bin.py @@ -60,7 +60,7 @@ class DocType: self.doc.save() def get_first_sle(self): - sle = sql(""" + sle = webnotes.conn.sql(""" select * from `tabStock Ledger Entry` where item_code = %s and warehouse = %s diff --git a/stock/doctype/delivery_note/delivery_note.py b/stock/doctype/delivery_note/delivery_note.py index ce06ce3d0bc..5242f60ea64 100644 --- a/stock/doctype/delivery_note/delivery_note.py +++ b/stock/doctype/delivery_note/delivery_note.py @@ -57,7 +57,7 @@ class DocType(SellingController): def set_actual_qty(self): for d in getlist(self.doclist, 'delivery_note_details'): if d.item_code and d.warehouse: - actual_qty = sql("select actual_qty from `tabBin` where item_code = '%s' and warehouse = '%s'" % (d.item_code, d.warehouse)) + actual_qty = webnotes.conn.sql("select actual_qty from `tabBin` where item_code = '%s' and warehouse = '%s'" % (d.item_code, d.warehouse)) d.actual_qty = actual_qty and flt(actual_qty[0][0]) or 0 @@ -133,7 +133,7 @@ class DocType(SellingController): def validate_proj_cust(self): """check for does customer belong to same project as entered..""" if self.doc.project_name and self.doc.customer: - res = sql("select name from `tabProject` where name = '%s' and (customer = '%s' or ifnull(customer,'')='')"%(self.doc.project_name, self.doc.customer)) + res = webnotes.conn.sql("select name from `tabProject` where name = '%s' and (customer = '%s' or ifnull(customer,'')='')"%(self.doc.project_name, self.doc.customer)) if not res: msgprint("Customer - %s does not belong to project - %s. \n\nIf you want to use project for multiple customers then please make customer details blank in project - %s."%(self.doc.customer,self.doc.project_name,self.doc.project_name)) raise Exception @@ -167,11 +167,11 @@ class DocType(SellingController): def update_current_stock(self): for d in getlist(self.doclist, 'delivery_note_details'): - bin = sql("select actual_qty from `tabBin` where item_code = %s and warehouse = %s", (d.item_code, d.warehouse), as_dict = 1) + bin = webnotes.conn.sql("select actual_qty from `tabBin` where item_code = %s and warehouse = %s", (d.item_code, d.warehouse), as_dict = 1) d.actual_qty = bin and flt(bin[0]['actual_qty']) or 0 for d in getlist(self.doclist, 'packing_details'): - bin = sql("select actual_qty, projected_qty from `tabBin` where item_code = %s and warehouse = %s", (d.item_code, d.warehouse), as_dict = 1) + bin = webnotes.conn.sql("select actual_qty, projected_qty from `tabBin` where item_code = %s and warehouse = %s", (d.item_code, d.warehouse), as_dict = 1) d.actual_qty = bin and flt(bin[0]['actual_qty']) or 0 d.projected_qty = bin and flt(bin[0]['projected_qty']) or 0 @@ -266,12 +266,12 @@ class DocType(SellingController): webnotes.msgprint("Packing Error:\n" + err_msg, raise_exception=1) def check_next_docstatus(self): - submit_rv = sql("select t1.name from `tabSales Invoice` t1,`tabSales Invoice Item` t2 where t1.name = t2.parent and t2.delivery_note = '%s' and t1.docstatus = 1" % (self.doc.name)) + submit_rv = webnotes.conn.sql("select t1.name from `tabSales Invoice` t1,`tabSales Invoice Item` t2 where t1.name = t2.parent and t2.delivery_note = '%s' and t1.docstatus = 1" % (self.doc.name)) if submit_rv: msgprint("Sales Invoice : " + cstr(submit_rv[0][0]) + " has already been submitted !") raise Exception , "Validation Error." - submit_in = sql("select t1.name from `tabInstallation Note` t1, `tabInstallation Note Item` t2 where t1.name = t2.parent and t2.prevdoc_docname = '%s' and t1.docstatus = 1" % (self.doc.name)) + submit_in = webnotes.conn.sql("select t1.name from `tabInstallation Note` t1, `tabInstallation Note Item` t2 where t1.name = t2.parent and t2.prevdoc_docname = '%s' and t1.docstatus = 1" % (self.doc.name)) if submit_in: msgprint("Installation Note : "+cstr(submit_in[0][0]) +" has already been submitted !") raise Exception , "Validation Error." diff --git a/stock/doctype/landed_cost_wizard/landed_cost_wizard.py b/stock/doctype/landed_cost_wizard/landed_cost_wizard.py index 52756320544..b9bbb068f19 100644 --- a/stock/doctype/landed_cost_wizard/landed_cost_wizard.py +++ b/stock/doctype/landed_cost_wizard/landed_cost_wizard.py @@ -32,7 +32,7 @@ class DocType: self.doclist = self.doc.clear_table(self.doclist,'lc_pr_details',1) self.check_mandatory() - pr = sql("select name from `tabPurchase Receipt` where docstatus = 1 and posting_date >= '%s' and posting_date <= '%s' and currency = '%s' order by name " % (self.doc.from_pr_date, self.doc.to_pr_date, self.doc.currency), as_dict = 1) + pr = webnotes.conn.sql("select name from `tabPurchase Receipt` where docstatus = 1 and posting_date >= '%s' and posting_date <= '%s' and currency = '%s' order by name " % (self.doc.from_pr_date, self.doc.to_pr_date, self.doc.currency), as_dict = 1) if len(pr)>200: msgprint("Please enter date of shorter duration as there are too many purchase receipt, hence it cannot be loaded.", raise_exception=1) @@ -50,14 +50,14 @@ class DocType: def validate_selected_pr(self): """Validate selected PR as submitted""" - invalid_pr = sql("SELECT name FROM `tabPurchase Receipt` WHERE docstatus != 1 and name in (%s)" % ("'" + "', '".join(self.selected_pr) + "'")) + invalid_pr = webnotes.conn.sql("SELECT name FROM `tabPurchase Receipt` WHERE docstatus != 1 and name in (%s)" % ("'" + "', '".join(self.selected_pr) + "'")) if invalid_pr: msgprint("Selected purchase receipts must be submitted. Following PR are not submitted: %s" % invalid_pr, raise_exception=1) def get_total_amt(self): """ Get sum of net total of all selected PR""" - return sql("SELECT SUM(net_total) FROM `tabPurchase Receipt` WHERE name in (%s)" % ("'" + "', '".join(self.selected_pr) + "'"))[0][0] + return webnotes.conn.sql("SELECT SUM(net_total) FROM `tabPurchase Receipt` WHERE name in (%s)" % ("'" + "', '".join(self.selected_pr) + "'"))[0][0] def add_charges_in_pr(self): @@ -73,7 +73,7 @@ class DocType: self.prwise_cost[pr] = self.prwise_cost.get(pr, 0) + amt cumulative_grand_total += amt - pr_oc_row = sql("select name from `tabPurchase Taxes and Charges` where parent = %s and category = 'Valuation' and add_deduct_tax = 'Add' and charge_type = 'Actual' and account_head = %s",(pr, lc.account_head)) + pr_oc_row = webnotes.conn.sql("select name from `tabPurchase Taxes and Charges` where parent = %s and category = 'Valuation' and add_deduct_tax = 'Add' and charge_type = 'Actual' and account_head = %s",(pr, lc.account_head)) if not pr_oc_row: # add if not exists ch = addchild(pr_obj.doc, 'purchase_tax_details', 'Purchase Taxes and Charges') ch.category = 'Valuation' @@ -88,7 +88,7 @@ class DocType: ch.idx = 500 # add at the end ch.save(1) else: # overwrite if exists - sql("update `tabPurchase Taxes and Charges` set rate = %s, tax_amount = %s where name = %s and parent = %s ", (amt, amt, pr_oc_row[0][0], pr)) + webnotes.conn.sql("update `tabPurchase Taxes and Charges` set rate = %s, tax_amount = %s where name = %s and parent = %s ", (amt, amt, pr_oc_row[0][0], pr)) def reset_other_charges(self, pr_obj): @@ -200,9 +200,9 @@ class DocType: d.save() if d.serial_no: self.update_serial_no(d.serial_no, d.valuation_rate) - sql("update `tabStock Ledger Entry` set incoming_rate = '%s' where voucher_detail_no = '%s'"%(flt(d.valuation_rate), d.name)) + webnotes.conn.sql("update `tabStock Ledger Entry` set incoming_rate = '%s' where voucher_detail_no = '%s'"%(flt(d.valuation_rate), d.name)) - res = sql("""select item_code, warehouse, posting_date, posting_time + res = webnotes.conn.sql("""select item_code, warehouse, posting_date, posting_time from `tabStock Ledger Entry` where voucher_detail_no = %s LIMIT 1""", d.name, as_dict=1) diff --git a/stock/doctype/purchase_receipt/purchase_receipt.py b/stock/doctype/purchase_receipt/purchase_receipt.py index 084f30cd593..1d48975b372 100644 --- a/stock/doctype/purchase_receipt/purchase_receipt.py +++ b/stock/doctype/purchase_receipt/purchase_receipt.py @@ -216,7 +216,7 @@ class DocType(BuyingController): def validate_inspection(self): for d in getlist(self.doclist, 'purchase_receipt_details'): #Enter inspection date for all items that require inspection - ins_reqd = sql("select inspection_required from `tabItem` where name = %s", + ins_reqd = webnotes.conn.sql("select inspection_required from `tabItem` where name = %s", (d.item_code,), as_dict = 1) ins_reqd = ins_reqd and ins_reqd[0]['inspection_required'] or 'No' if ins_reqd == 'Yes' and not d.qa_no: @@ -269,7 +269,7 @@ class DocType(BuyingController): sr.save() def check_next_docstatus(self): - submit_rv = sql("select t1.name from `tabPurchase Invoice` t1,`tabPurchase Invoice Item` t2 where t1.name = t2.parent and t2.purchase_receipt = '%s' and t1.docstatus = 1" % (self.doc.name)) + submit_rv = webnotes.conn.sql("select t1.name from `tabPurchase Invoice` t1,`tabPurchase Invoice Item` t2 where t1.name = t2.parent and t2.purchase_receipt = '%s' and t1.docstatus = 1" % (self.doc.name)) if submit_rv: msgprint("Purchase Invoice : " + cstr(self.submit_rv[0][0]) + " has already been submitted !") raise Exception , "Validation Error." @@ -282,7 +282,7 @@ class DocType(BuyingController): # 1.Check if Purchase Invoice has been submitted against current Purchase Order # pc_obj.check_docstatus(check = 'Next', doctype = 'Purchase Invoice', docname = self.doc.name, detail_doctype = 'Purchase Invoice Item') - submitted = sql("select t1.name from `tabPurchase Invoice` t1,`tabPurchase Invoice Item` t2 where t1.name = t2.parent and t2.purchase_receipt = '%s' and t1.docstatus = 1" % self.doc.name) + submitted = webnotes.conn.sql("select t1.name from `tabPurchase Invoice` t1,`tabPurchase Invoice Item` t2 where t1.name = t2.parent and t2.purchase_receipt = '%s' and t1.docstatus = 1" % self.doc.name) if submitted: msgprint("Purchase Invoice : " + cstr(submitted[0][0]) + " has already been submitted !") raise Exception @@ -313,7 +313,7 @@ class DocType(BuyingController): def get_current_stock(self): for d in getlist(self.doclist, 'pr_raw_material_details'): if self.doc.supplier_warehouse: - bin = sql("select actual_qty from `tabBin` where item_code = %s and warehouse = %s", (d.rm_item_code, self.doc.supplier_warehouse), as_dict = 1) + bin = webnotes.conn.sql("select actual_qty from `tabBin` where item_code = %s and warehouse = %s", (d.rm_item_code, self.doc.supplier_warehouse), as_dict = 1) d.current_stock = bin and flt(bin[0]['actual_qty']) or 0 diff --git a/stock/doctype/stock_entry/stock_entry.py b/stock/doctype/stock_entry/stock_entry.py index b5e1edf09c2..1fdd609a62e 100644 --- a/stock/doctype/stock_entry/stock_entry.py +++ b/stock/doctype/stock_entry/stock_entry.py @@ -387,7 +387,7 @@ class DocType(StockController): def get_item_details(self, arg): arg = json.loads(arg) - item = sql("""select stock_uom, description, item_name from `tabItem` + item = webnotes.conn.sql("""select stock_uom, description, item_name from `tabItem` where name = %s and (ifnull(end_of_life,'')='' or end_of_life ='0000-00-00' or end_of_life > now())""", (arg.get('item_code')), as_dict = 1) if not item: @@ -411,7 +411,7 @@ class DocType(StockController): def get_uom_details(self, arg = ''): arg, ret = eval(arg), {} - uom = sql("""select conversion_factor from `tabUOM Conversion Detail` + uom = webnotes.conn.sql("""select conversion_factor from `tabUOM Conversion Detail` where parent = %s and uom = %s""", (arg['item_code'], arg['uom']), as_dict = 1) if not uom: msgprint("There is no Conversion Factor for UOM '%s' in Item '%s'" % (arg['uom'], @@ -522,7 +522,7 @@ class DocType(StockController): if self.doc.use_multi_level_bom: # get all raw materials with sub assembly childs - fl_bom_sa_child_item = sql("""select + fl_bom_sa_child_item = webnotes.conn.sql("""select fb.item_code, ifnull(sum(fb.qty_consumed_per_unit),0)*%s as qty, fb.description, @@ -542,7 +542,7 @@ class DocType(StockController): _make_items_dict(fl_bom_sa_child_item) else: # get only BOM items - fl_bom_sa_items = sql("""select + fl_bom_sa_items = webnotes.conn.sql("""select `tabItem`.item_code, ifnull(sum(`tabBOM Item`.qty_consumed_per_unit), 0) *%s as qty, `tabItem`.description, @@ -600,7 +600,7 @@ class DocType(StockController): def get_issued_qty(self): issued_item_qty = {} - result = sql("""select t1.item_code, sum(t1.qty) + result = webnotes.conn.sql("""select t1.item_code, sum(t1.qty) from `tabStock Entry Detail` t1, `tabStock Entry` t2 where t1.parent = t2.name and t2.production_order = %s and t2.docstatus = 1 and t2.purpose = 'Material Transfer' @@ -666,7 +666,7 @@ class DocType(StockController): def get_cust_addr(self): from utilities.transaction_base import get_default_address, get_address_display - res = sql("select customer_name from `tabCustomer` where name = '%s'"%self.doc.customer) + res = webnotes.conn.sql("select customer_name from `tabCustomer` where name = '%s'"%self.doc.customer) address_display = None customer_address = get_default_address("customer", self.doc.customer) if customer_address: @@ -687,7 +687,7 @@ class DocType(StockController): def get_supp_addr(self): from utilities.transaction_base import get_default_address, get_address_display - res = sql("""select supplier_name from `tabSupplier` + res = webnotes.conn.sql("""select supplier_name from `tabSupplier` where name=%s""", self.doc.supplier) address_display = None supplier_address = get_default_address("customer", self.doc.customer) diff --git a/stock/doctype/stock_uom_replace_utility/stock_uom_replace_utility.py b/stock/doctype/stock_uom_replace_utility/stock_uom_replace_utility.py index 2ec9debf7f2..1f1bafabc8b 100644 --- a/stock/doctype/stock_uom_replace_utility/stock_uom_replace_utility.py +++ b/stock/doctype/stock_uom_replace_utility/stock_uom_replace_utility.py @@ -33,7 +33,7 @@ class DocType: msgprint("Please Enter Conversion Factor.") raise Exception - stock_uom = sql("select stock_uom from `tabItem` where name = '%s'" % self.doc.item_code) + stock_uom = webnotes.conn.sql("select stock_uom from `tabItem` where name = '%s'" % self.doc.item_code) stock_uom = stock_uom and stock_uom[0][0] if cstr(self.doc.new_stock_uom) == cstr(stock_uom): msgprint("Item Master is already updated with New Stock UOM " + cstr(self.doc.new_stock_uom)) @@ -49,9 +49,9 @@ class DocType: def update_bin(self): # update bin if flt(self.doc.conversion_factor) != flt(1): - sql("update `tabBin` set stock_uom = '%s' , indented_qty = ifnull(indented_qty,0) * %s, ordered_qty = ifnull(ordered_qty,0) * %s, reserved_qty = ifnull(reserved_qty,0) * %s, planned_qty = ifnull(planned_qty,0) * %s, projected_qty = actual_qty + ordered_qty + indented_qty + planned_qty - reserved_qty where item_code = '%s'" % (self.doc.new_stock_uom, self.doc.conversion_factor, self.doc.conversion_factor, self.doc.conversion_factor, self.doc.conversion_factor, self.doc.item_code) ) + webnotes.conn.sql("update `tabBin` set stock_uom = '%s' , indented_qty = ifnull(indented_qty,0) * %s, ordered_qty = ifnull(ordered_qty,0) * %s, reserved_qty = ifnull(reserved_qty,0) * %s, planned_qty = ifnull(planned_qty,0) * %s, projected_qty = actual_qty + ordered_qty + indented_qty + planned_qty - reserved_qty where item_code = '%s'" % (self.doc.new_stock_uom, self.doc.conversion_factor, self.doc.conversion_factor, self.doc.conversion_factor, self.doc.conversion_factor, self.doc.item_code) ) else: - sql("update `tabBin` set stock_uom = '%s' where item_code = '%s'" % (self.doc.new_stock_uom, self.doc.item_code) ) + webnotes.conn.sql("update `tabBin` set stock_uom = '%s' where item_code = '%s'" % (self.doc.new_stock_uom, self.doc.item_code) ) # acknowledge user msgprint(" All Bins Updated Successfully.") @@ -61,16 +61,16 @@ class DocType: from stock.stock_ledger import update_entries_after if flt(self.doc.conversion_factor) != flt(1): - sql("update `tabStock Ledger Entry` set stock_uom = '%s', actual_qty = ifnull(actual_qty,0) * '%s' where item_code = '%s' " % (self.doc.new_stock_uom, self.doc.conversion_factor, self.doc.item_code)) + webnotes.conn.sql("update `tabStock Ledger Entry` set stock_uom = '%s', actual_qty = ifnull(actual_qty,0) * '%s' where item_code = '%s' " % (self.doc.new_stock_uom, self.doc.conversion_factor, self.doc.item_code)) else: - sql("update `tabStock Ledger Entry` set stock_uom = '%s' where item_code = '%s' " % (self.doc.new_stock_uom, self.doc.item_code)) + webnotes.conn.sql("update `tabStock Ledger Entry` set stock_uom = '%s' where item_code = '%s' " % (self.doc.new_stock_uom, self.doc.item_code)) # acknowledge user msgprint("Stock Ledger Entries Updated Successfully.") # update item valuation if flt(self.doc.conversion_factor) != flt(1): - wh = sql("select name from `tabWarehouse`") + wh = webnotes.conn.sql("select name from `tabWarehouse`") for w in wh: update_entries_after({"item_code": self.doc.item_code, "warehouse": w[0]}) diff --git a/stock/doctype/warehouse/warehouse.py b/stock/doctype/warehouse/warehouse.py index b23f043a3da..54d0b15836b 100644 --- a/stock/doctype/warehouse/warehouse.py +++ b/stock/doctype/warehouse/warehouse.py @@ -21,7 +21,7 @@ class DocType: def get_bin(self, item_code, warehouse=None): warehouse = warehouse or self.doc.name - bin = sql("select name from tabBin where item_code = %s and \ + bin = webnotes.conn.sql("select name from tabBin where item_code = %s and \ warehouse = %s", (item_code, warehouse)) bin = bin and bin[0][0] or '' if not bin: @@ -163,22 +163,22 @@ class DocType: def on_trash(self): # delete bin - bins = sql("select * from `tabBin` where warehouse = %s", self.doc.name, as_dict=1) + bins = webnotes.conn.sql("select * from `tabBin` where warehouse = %s", self.doc.name, as_dict=1) for d in bins: if d['actual_qty'] or d['reserved_qty'] or d['ordered_qty'] or \ d['indented_qty'] or d['projected_qty'] or d['planned_qty']: msgprint("""Warehouse: %s can not be deleted as qty exists for item: %s""" % (self.doc.name, d['item_code']), raise_exception=1) else: - sql("delete from `tabBin` where name = %s", d['name']) + webnotes.conn.sql("delete from `tabBin` where name = %s", d['name']) # delete cancelled sle - if sql("""select name from `tabStock Ledger Entry` + if webnotes.conn.sql("""select name from `tabStock Ledger Entry` where warehouse = %s and ifnull('is_cancelled', '') = 'No'""", self.doc.name): msgprint("""Warehosue can not be deleted as stock ledger entry exists for this warehouse.""", raise_exception=1) else: - sql("delete from `tabStock Ledger Entry` where warehouse = %s", self.doc.name) + webnotes.conn.sql("delete from `tabStock Ledger Entry` where warehouse = %s", self.doc.name) def on_rename(self, newdn, olddn, merge=False): if merge: diff --git a/support/doctype/customer_issue/customer_issue.py b/support/doctype/customer_issue/customer_issue.py index 3773cdf3605..c099bf699ee 100644 --- a/support/doctype/customer_issue/customer_issue.py +++ b/support/doctype/customer_issue/customer_issue.py @@ -27,7 +27,7 @@ class DocType(TransactionBase): self.doc.resolved_by = webnotes.session.user def on_cancel(self): - lst = sql("select t1.name from `tabMaintenance Visit` t1, `tabMaintenance Visit Purpose` t2 where t2.parent = t1.name and t2.prevdoc_docname = '%s' and t1.docstatus!=2"%(self.doc.name)) + lst = webnotes.conn.sql("select t1.name from `tabMaintenance Visit` t1, `tabMaintenance Visit Purpose` t2 where t2.parent = t1.name and t2.prevdoc_docname = '%s' and t1.docstatus!=2"%(self.doc.name)) if lst: lst1 = ','.join([x[0] for x in lst]) msgprint("Maintenance Visit No. "+lst1+" already created against this customer issue. So can not be Cancelled") diff --git a/support/doctype/maintenance_schedule/maintenance_schedule.py b/support/doctype/maintenance_schedule/maintenance_schedule.py index 4bb121767c7..1682da5afa5 100644 --- a/support/doctype/maintenance_schedule/maintenance_schedule.py +++ b/support/doctype/maintenance_schedule/maintenance_schedule.py @@ -19,7 +19,7 @@ class DocType(TransactionBase): self.doclist = doclist def get_item_details(self, item_code): - item = sql("select item_name, description from `tabItem` where name = '%s'" %(item_code), as_dict=1) + item = webnotes.conn.sql("select item_name, description from `tabItem` where name = '%s'" %(item_code), as_dict=1) ret = { 'item_name': item and item[0]['item_name'] or '', 'description' : item and item[0]['description'] or '' @@ -29,7 +29,7 @@ class DocType(TransactionBase): def generate_schedule(self): self.doclist = self.doc.clear_table(self.doclist, 'maintenance_schedule_detail') count = 0 - sql("delete from `tabMaintenance Schedule Detail` where parent='%s'" %(self.doc.name)) + webnotes.conn.sql("delete from `tabMaintenance Schedule Detail` where parent='%s'" %(self.doc.name)) for d in getlist(self.doclist, 'item_maintenance_detail'): self.validate_maintenance_detail() s_list =[] @@ -66,7 +66,7 @@ class DocType(TransactionBase): email_map[d.incharge_name] = webnotes.bean("Sales Person", d.incharge_name).run_method("get_email_id") - scheduled_date =sql("select scheduled_date from `tabMaintenance Schedule Detail` \ + scheduled_date =webnotes.conn.sql("select scheduled_date from `tabMaintenance Schedule Detail` \ where incharge_name='%s' and item_code='%s' and parent='%s' " %(d.incharge_name, \ d.item_code, self.doc.name), as_dict=1) @@ -171,7 +171,7 @@ class DocType(TransactionBase): def validate_sales_order(self): for d in getlist(self.doclist, 'item_maintenance_detail'): if d.prevdoc_docname: - chk = sql("select t1.name from `tabMaintenance Schedule` t1, `tabMaintenance Schedule Item` t2 where t2.parent=t1.name and t2.prevdoc_docname=%s and t1.docstatus=1", d.prevdoc_docname) + chk = webnotes.conn.sql("select t1.name from `tabMaintenance Schedule` t1, `tabMaintenance Schedule Item` t2 where t2.parent=t1.name and t2.prevdoc_docname=%s and t1.docstatus=1", d.prevdoc_docname) if chk: msgprint("Maintenance Schedule against "+d.prevdoc_docname+" already exist") raise Exception @@ -185,7 +185,7 @@ class DocType(TransactionBase): cur_s_no = cur_serial_no.split(',') for x in cur_s_no: - chk = sql("select name, status from `tabSerial No` where docstatus!=2 and name=%s", (x)) + chk = webnotes.conn.sql("select name, status from `tabSerial No` where docstatus!=2 and name=%s", (x)) chk1 = chk and chk[0][0] or '' status = chk and chk[0][1] or '' @@ -208,7 +208,7 @@ class DocType(TransactionBase): cur_s_no = cur_serial_no.split(',') for x in cur_s_no: - dt = sql("select delivery_date from `tabSerial No` where name = %s", x) + dt = webnotes.conn.sql("select delivery_date from `tabSerial No` where name = %s", x) dt = dt and dt[0][0] or '' if dt: @@ -224,7 +224,7 @@ class DocType(TransactionBase): cur_s_no = cur_serial_no.split(',') for x in cur_s_no: - sql("update `tabSerial No` set amc_expiry_date = '%s', maintenance_status = 'Under AMC' where name = '%s'"% (amc_end_date,x)) + webnotes.conn.sql("update `tabSerial No` set amc_expiry_date = '%s', maintenance_status = 'Under AMC' where name = '%s'"% (amc_end_date,x)) def on_update(self): webnotes.conn.set(self.doc, 'status', 'Draft') @@ -232,7 +232,7 @@ class DocType(TransactionBase): def validate_serial_no_warranty(self): for d in getlist(self.doclist, 'item_maintenance_detail'): if cstr(d.serial_no).strip(): - dt = sql("""select warranty_expiry_date, amc_expiry_date + dt = webnotes.conn.sql("""select warranty_expiry_date, amc_expiry_date from `tabSerial No` where name = %s""", d.serial_no, as_dict=1) if dt[0]['warranty_expiry_date'] and dt[0]['warranty_expiry_date'] >= d.start_date: webnotes.msgprint("""Serial No: %s is already under warranty upto %s. diff --git a/support/doctype/maintenance_visit/maintenance_visit.py b/support/doctype/maintenance_visit/maintenance_visit.py index dbb2880ac91..60cc3712a60 100644 --- a/support/doctype/maintenance_visit/maintenance_visit.py +++ b/support/doctype/maintenance_visit/maintenance_visit.py @@ -18,7 +18,7 @@ class DocType(TransactionBase): self.doclist = doclist def get_item_details(self, item_code): - item = sql("select item_name,description from `tabItem` where name = '%s'" %(item_code), as_dict=1) + item = webnotes.conn.sql("select item_name,description from `tabItem` where name = '%s'" %(item_code), as_dict=1) ret = { 'item_name' : item and item[0]['item_name'] or '', 'description' : item and item[0]['description'] or '' @@ -27,7 +27,7 @@ class DocType(TransactionBase): def validate_serial_no(self): for d in getlist(self.doclist, 'maintenance_visit_details'): - if d.serial_no and not sql("select name from `tabSerial No` where name = '%s' and docstatus != 2" % d.serial_no): + if d.serial_no and not webnotes.conn.sql("select name from `tabSerial No` where name = '%s' and docstatus != 2" % d.serial_no): msgprint("Serial No: "+ d.serial_no + " not exists in the system") raise Exception @@ -51,7 +51,7 @@ class DocType(TransactionBase): elif self.doc.completion_status == 'Partially Completed': status = 'Work In Progress' else: - nm = sql("select t1.name, t1.mntc_date, t2.service_person, t2.work_done from `tabMaintenance Visit` t1, `tabMaintenance Visit Purpose` t2 where t2.parent = t1.name and t1.completion_status = 'Partially Completed' and t2.prevdoc_docname = %s and t1.name!=%s and t1.docstatus = 1 order by t1.name desc limit 1", (d.prevdoc_docname, self.doc.name)) + nm = webnotes.conn.sql("select t1.name, t1.mntc_date, t2.service_person, t2.work_done from `tabMaintenance Visit` t1, `tabMaintenance Visit Purpose` t2 where t2.parent = t1.name and t1.completion_status = 'Partially Completed' and t2.prevdoc_docname = %s and t1.name!=%s and t1.docstatus = 1 order by t1.name desc limit 1", (d.prevdoc_docname, self.doc.name)) if nm: status = 'Work In Progress' @@ -64,7 +64,7 @@ class DocType(TransactionBase): service_person = '' work_done = '' - sql("update `tabCustomer Issue` set resolution_date=%s, resolved_by=%s, resolution_details=%s, status=%s where name =%s",(mntc_date,service_person,work_done,status,d.prevdoc_docname)) + webnotes.conn.sql("update `tabCustomer Issue` set resolution_date=%s, resolved_by=%s, resolution_details=%s, status=%s where name =%s",(mntc_date,service_person,work_done,status,d.prevdoc_docname)) def check_if_last_visit(self): @@ -76,7 +76,7 @@ class DocType(TransactionBase): check_for_doctype = d.prevdoc_doctype if check_for_docname: - check = sql("select t1.name from `tabMaintenance Visit` t1, `tabMaintenance Visit Purpose` t2 where t2.parent = t1.name and t1.name!=%s and t2.prevdoc_docname=%s and t1.docstatus = 1 and (t1.mntc_date > %s or (t1.mntc_date = %s and t1.mntc_time > %s))", (self.doc.name, check_for_docname, self.doc.mntc_date, self.doc.mntc_date, self.doc.mntc_time)) + check = webnotes.conn.sql("select t1.name from `tabMaintenance Visit` t1, `tabMaintenance Visit Purpose` t2 where t2.parent = t1.name and t1.name!=%s and t2.prevdoc_docname=%s and t1.docstatus = 1 and (t1.mntc_date > %s or (t1.mntc_date = %s and t1.mntc_time > %s))", (self.doc.name, check_for_docname, self.doc.mntc_date, self.doc.mntc_date, self.doc.mntc_time)) if check: check_lst = [x[0] for x in check] diff --git a/utilities/doctype/contact/contact.py b/utilities/doctype/contact/contact.py index 84c8a59de85..58437f1a62d 100644 --- a/utilities/doctype/contact/contact.py +++ b/utilities/doctype/contact/contact.py @@ -35,25 +35,24 @@ class DocType(TransactionBase): self.validate_primary_contact() def validate_primary_contact(self): - sql = webnotes.conn.sql if self.doc.is_primary_contact == 1: if self.doc.customer: - sql("update tabContact set is_primary_contact=0 where customer = '%s'" % (self.doc.customer)) + webnotes.conn.sql("update tabContact set is_primary_contact=0 where customer = '%s'" % (self.doc.customer)) elif self.doc.supplier: - sql("update tabContact set is_primary_contact=0 where supplier = '%s'" % (self.doc.supplier)) + webnotes.conn.sql("update tabContact set is_primary_contact=0 where supplier = '%s'" % (self.doc.supplier)) elif self.doc.sales_partner: - sql("update tabContact set is_primary_contact=0 where sales_partner = '%s'" % (self.doc.sales_partner)) + webnotes.conn.sql("update tabContact set is_primary_contact=0 where sales_partner = '%s'" % (self.doc.sales_partner)) else: if self.doc.customer: - if not sql("select name from tabContact where is_primary_contact=1 and customer = '%s'" % (self.doc.customer)): + if not webnotes.conn.sql("select name from tabContact where is_primary_contact=1 and customer = '%s'" % (self.doc.customer)): self.doc.is_primary_contact = 1 elif self.doc.supplier: - if not sql("select name from tabContact where is_primary_contact=1 and supplier = '%s'" % (self.doc.supplier)): + if not webnotes.conn.sql("select name from tabContact where is_primary_contact=1 and supplier = '%s'" % (self.doc.supplier)): self.doc.is_primary_contact = 1 elif self.doc.sales_partner: - if not sql("select name from tabContact where is_primary_contact=1 and sales_partner = '%s'" % (self.doc.sales_partner)): + if not webnotes.conn.sql("select name from tabContact where is_primary_contact=1 and sales_partner = '%s'" % (self.doc.sales_partner)): self.doc.is_primary_contact = 1 def on_trash(self): webnotes.conn.sql("""update `tabSupport Ticket` set contact='' where contact=%s""", - self.doc.name) \ No newline at end of file + self.doc.name) diff --git a/utilities/doctype/sms_control/sms_control.py b/utilities/doctype/sms_control/sms_control.py index d72db529dd8..f183920afc4 100644 --- a/utilities/doctype/sms_control/sms_control.py +++ b/utilities/doctype/sms_control/sms_control.py @@ -48,7 +48,7 @@ class DocType: def get_contact_number(self, arg): "returns mobile number of the contact" args = load_json(arg) - number = sql("""select mobile_no, phone from tabContact where name=%s and %s=%s""" % + number = webnotes.conn.sql("""select mobile_no, phone from tabContact where name=%s and %s=%s""" % ('%s', args['key'], '%s'), (args['contact_name'], args['value'])) return number and (number[0][0] or number[0][1]) or '' From 16371b721233b0537199373f355851185975fe5b Mon Sep 17 00:00:00 2001 From: Pratik Vyas Date: Wed, 18 Sep 2013 18:31:03 +0530 Subject: [PATCH 003/200] refactor stock ledger to be thread safe --- stock/stock_ledger.py | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/stock/stock_ledger.py b/stock/stock_ledger.py index f0619c7384d..0e8a341a4cd 100644 --- a/stock/stock_ledger.py +++ b/stock/stock_ledger.py @@ -10,7 +10,9 @@ import json # future reposting class NegativeStockError(webnotes.ValidationError): pass -_exceptions = [] +_exceptions = webnotes.local('stockledger_exceptions') + +# _exceptions = [] def update_entries_after(args, verbose=1): """ update valution rate and qty after transaction @@ -23,8 +25,8 @@ def update_entries_after(args, verbose=1): "posting_time": "12:00" } """ - global _exceptions - _exceptions = [] + if not _exceptions: + webnotes.local.stockledger_exceptions = [] previous_sle = get_sle_before_datetime(args) @@ -140,10 +142,12 @@ def validate_negative_stock(qty_after_transaction, sle): will not consider cancelled entries """ diff = qty_after_transaction + flt(sle.actual_qty) + + if not _exceptions: + webnotes.local.stockledger_exceptions = [] if diff < 0 and abs(diff) > 0.0001: # negative stock! - global _exceptions exc = sle.copy().update({"diff": diff}) _exceptions.append(exc) return False @@ -277,4 +281,4 @@ def get_previous_sle(args, for_update=False): sle = get_stock_ledger_entries(args, ["name != %(sle)s", "timestamp(posting_date, posting_time) <= timestamp(%(posting_date)s, %(posting_time)s)"], "desc", "limit 1", for_update=for_update) - return sle and sle[0] or {} \ No newline at end of file + return sle and sle[0] or {} From ea810509d3dae6093904cc9fa410908927f778be Mon Sep 17 00:00:00 2001 From: Pratik Vyas Date: Wed, 18 Sep 2013 18:35:47 +0530 Subject: [PATCH 004/200] refactor newsletter for naming_series global --- support/doctype/newsletter/newsletter.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/support/doctype/newsletter/newsletter.py b/support/doctype/newsletter/newsletter.py index b201cc55865..9a27d839f8b 100644 --- a/support/doctype/newsletter/newsletter.py +++ b/support/doctype/newsletter/newsletter.py @@ -105,7 +105,6 @@ def get_lead_options(): } -lead_naming_series = None def create_lead(email_id): """create a lead if it does not exist""" from email.utils import parseaddr @@ -119,7 +118,7 @@ def create_lead(email_id): "email_id": email_id, "lead_name": real_name or email_id, "status": "Contacted", - "naming_series": lead_naming_series or get_lead_naming_series(), + "naming_series": get_lead_naming_series(), "company": webnotes.conn.get_default("company"), "source": "Email" }) @@ -127,7 +126,7 @@ def create_lead(email_id): def get_lead_naming_series(): """gets lead's default naming series""" - global lead_naming_series + lead_naming_series = None naming_series_field = webnotes.get_doctype("Lead").get_field("naming_series") if naming_series_field.default: lead_naming_series = naming_series_field.default From 7782e83d33c1f39fe0c54d92fed57508528d6a66 Mon Sep 17 00:00:00 2001 From: Pratik Vyas Date: Wed, 18 Sep 2013 18:52:10 +0530 Subject: [PATCH 005/200] refactor upload attendance for doclist global --- hr/doctype/upload_attendance/upload_attendance.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/hr/doctype/upload_attendance/upload_attendance.py b/hr/doctype/upload_attendance/upload_attendance.py index c1344b90e41..5e2b02ea1fd 100644 --- a/hr/doctype/upload_attendance/upload_attendance.py +++ b/hr/doctype/upload_attendance/upload_attendance.py @@ -9,7 +9,8 @@ from webnotes.utils import cstr, add_days, date_diff from webnotes import msgprint, _ from webnotes.utils.datautils import UnicodeWriter -doclist = None +# doclist = None +doclist = webnotes.local('uploadattendance_doclist') class DocType(): def __init__(self, doc, doclist=[]): @@ -22,8 +23,7 @@ def get_template(): raise webnotes.PermissionError args = webnotes.form_dict - global doclist - doclist = webnotes.model.doctype.get("Attendance") + webnotes.local.uploadattendance_doclist = webnotes.model.doctype.get("Attendance") w = UnicodeWriter() w = add_header(w) @@ -144,4 +144,4 @@ def upload(): webnotes.conn.rollback() else: webnotes.conn.commit() - return {"messages": ret, "error": error} \ No newline at end of file + return {"messages": ret, "error": error} From cfed8c44b4a0f699c6e00f11f47cb70ecf324b5c Mon Sep 17 00:00:00 2001 From: Pratik Vyas Date: Sat, 21 Sep 2013 15:16:47 +0530 Subject: [PATCH 006/200] conf migration --- setup/doctype/backup_manager/backup_googledrive.py | 4 ++-- setup/doctype/email_digest/email_digest.py | 2 +- startup/boot.py | 4 ++-- startup/event_handlers.py | 4 ++-- support/doctype/newsletter/newsletter.py | 2 +- utilities/demo/demo_control_panel.py | 4 ++-- utilities/demo/make_demo.py | 4 ++-- utilities/demo/make_erpnext_demo.py | 4 ++-- 8 files changed, 14 insertions(+), 14 deletions(-) diff --git a/setup/doctype/backup_manager/backup_googledrive.py b/setup/doctype/backup_manager/backup_googledrive.py index 5d7b6ad0fa1..ee795186da5 100644 --- a/setup/doctype/backup_manager/backup_googledrive.py +++ b/setup/doctype/backup_manager/backup_googledrive.py @@ -113,7 +113,7 @@ def backup_to_gdrive(): def get_gdrive_flow(): from oauth2client.client import OAuth2WebServerFlow - import conf + from webnotes import conf if not hasattr(conf, "gdrive_client_id"): webnotes.msgprint(_("Please set Google Drive access keys in") + " conf.py", @@ -169,4 +169,4 @@ def create_folder(name, service, folder_id): return database['id'] if __name__=="__main__": - backup_to_gdrive() \ No newline at end of file + backup_to_gdrive() diff --git a/setup/doctype/email_digest/email_digest.py b/setup/doctype/email_digest/email_digest.py index 39e377a6014..2a9acaa8b92 100644 --- a/setup/doctype/email_digest/email_digest.py +++ b/setup/doctype/email_digest/email_digest.py @@ -457,7 +457,7 @@ def send(): from webnotes.utils import getdate now_date = now_datetime().date() - import conf + from webnotes import conf if hasattr(conf, "expires_on") and now_date > getdate(conf.expires_on): # do not send email digests to expired accounts return diff --git a/startup/boot.py b/startup/boot.py index 886b805db43..20887f720c6 100644 --- a/startup/boot.py +++ b/startup/boot.py @@ -32,7 +32,7 @@ def boot_session(bootinfo): # load subscription info - import conf + from webnotes import conf for key in ['max_users', 'expires_on', 'max_space', 'status', 'commercial_support']: if hasattr(conf, key): bootinfo[key] = getattr(conf, key) @@ -53,4 +53,4 @@ def get_letter_heads(): ret = webnotes.conn.sql("""select name, content from `tabLetter Head` where ifnull(disabled,0)=0""") return dict(ret) - \ No newline at end of file + diff --git a/startup/event_handlers.py b/startup/event_handlers.py index 57345f3ca06..a333857b1b2 100644 --- a/startup/event_handlers.py +++ b/startup/event_handlers.py @@ -39,7 +39,7 @@ def on_logout(login_manager): def check_if_expired(): """check if account is expired. If expired, do not allow login""" - import conf + from webnotes import conf # check if expires_on is specified if not hasattr(conf, 'expires_on'): return @@ -75,4 +75,4 @@ def comment_added(doc): """add comment to feed""" home.make_feed('Comment', doc.comment_doctype, doc.comment_docname, doc.comment_by, '"' + doc.comment + '"', '#6B24B3') - \ No newline at end of file + diff --git a/support/doctype/newsletter/newsletter.py b/support/doctype/newsletter/newsletter.py index 9a27d839f8b..13ad47a0d8e 100644 --- a/support/doctype/newsletter/newsletter.py +++ b/support/doctype/newsletter/newsletter.py @@ -90,7 +90,7 @@ class DocType(): webnotes.msgprint(_("""Please save the Newsletter before sending."""), raise_exception=1) - import conf + from webnotes import conf if getattr(conf, "status", None) == "Trial": webnotes.msgprint(_("""Sending newsletters is not allowed for Trial users, \ to prevent abuse of this feature."""), raise_exception=1) diff --git a/utilities/demo/demo_control_panel.py b/utilities/demo/demo_control_panel.py index 1f381d5eb6e..1da690245ca 100644 --- a/utilities/demo/demo_control_panel.py +++ b/utilities/demo/demo_control_panel.py @@ -1,7 +1,7 @@ def on_login(self): from webnotes.utils import validate_email_add - import conf + from webnotes import conf if hasattr(conf, "demo_notify_url"): if webnotes.form_dict.lead_email and validate_email_add(webnotes.form_dict.lead_email): import requests @@ -10,4 +10,4 @@ "subject":"Logged into Demo", "sender": webnotes.form_dict.lead_email, "message": "via demo.erpnext.com" - }) \ No newline at end of file + }) diff --git a/utilities/demo/make_demo.py b/utilities/demo/make_demo.py index a526c2a301e..883186791a9 100644 --- a/utilities/demo/make_demo.py +++ b/utilities/demo/make_demo.py @@ -355,7 +355,7 @@ def how_many(doctype): def install(): print "Creating Fresh Database..." from webnotes.install_lib.install import Installer - import conf + from webnotes import conf inst = Installer('root') inst.import_from_db(conf.demo_db_name, verbose = 1) @@ -414,4 +414,4 @@ def import_data(dt, submit=False, overwrite=False): if submit: webnotes.form_dict["params"] = json.dumps({"_submit": 1}) webnotes.uploaded_file = os.path.join(os.path.dirname(__file__), "demo_docs", doctype+".csv") - upload(overwrite=overwrite) \ No newline at end of file + upload(overwrite=overwrite) diff --git a/utilities/demo/make_erpnext_demo.py b/utilities/demo/make_erpnext_demo.py index 766da2612f2..70e7322ea83 100644 --- a/utilities/demo/make_erpnext_demo.py +++ b/utilities/demo/make_erpnext_demo.py @@ -42,7 +42,7 @@ def make_demo_user(): p.doc.last_name = "User" p.doc.enabled = 1 p.doc.user_type = "ERPNext Demo" - p.doc.send_invite_email = 0 + # p.doc.send_invite_email = 0 p.doc.new_password = "demo" p.insert() add_roles(p) @@ -118,4 +118,4 @@ def make_demo_on_login_script(): webnotes.conn.commit() if __name__=="__main__": - make_demo_app() \ No newline at end of file + make_demo_app() From 0eb811a51808b1c7aaae1a3dd8135424f70a972f Mon Sep 17 00:00:00 2001 From: Pratik Vyas Date: Mon, 23 Sep 2013 16:04:50 +0530 Subject: [PATCH 007/200] [minor] remove send_invite_email field from demo docs --- utilities/demo/demo_docs/Profile.csv | 80 ++++++++++++++-------------- utilities/demo/make_erpnext_demo.py | 2 - 2 files changed, 40 insertions(+), 42 deletions(-) diff --git a/utilities/demo/demo_docs/Profile.csv b/utilities/demo/demo_docs/Profile.csv index 2e7a2cee15e..eb456c16ad9 100644 --- a/utilities/demo/demo_docs/Profile.csv +++ b/utilities/demo/demo_docs/Profile.csv @@ -1,40 +1,40 @@ -Data Import Template,,,,,,,,,,,,,,,,,,,,, -Table:,Profile,,,,,,,,,,,,,,,,,,,, -,,,,,,,,,,,,,,,,,,,,, -,,,,,,,,,,,,,,,,,,,,, -Notes:,,,,,,,,,,,,,,,,,,,,, -Please do not change the template headings.,,,,,,,,,,,,,,,,,,,,, -First data column must be blank.,,,,,,,,,,,,,,,,,,,,, -"If you are uploading new records, leave the ""name"" (ID) column blank.",,,,,,,,,,,,,,,,,,,,, -"If you are uploading new records, ""Naming Series"" becomes mandatory, if present.",,,,,,,,,,,,,,,,,,,,, -Only mandatory fields are necessary for new records. You can delete non-mandatory columns if you wish.,,,,,,,,,,,,,,,,,,,,, -"For updating, you can update only selective columns.",,,,,,,,,,,,,,,,,,,,, -You can only upload upto 5000 records in one go. (may be less in some cases),,,,,,,,,,,,,,,,,,,,, -,,,,,,,,,,,,,,,,,,,,, -DocType:,Profile,,,,,,,,,,,,,,,,,,,, -Column Labels:,ID,Email,First Name,User Type,Enabled,Middle Name (Optional),Last Name,Send Invite Email,Language,Birth Date,Gender,New Password,User Image,Background Image,Bio,Email Signature,Login After,Login Before,Restrict IP,Last Login,Last IP -Column Name:,name,email,first_name,user_type,enabled,middle_name,last_name,send_invite_email,language,birth_date,gender,new_password,user_image,background_image,bio,email_signature,login_after,login_before,restrict_ip,last_login,last_ip -Mandatory:,Yes,Yes,Yes,Yes,No,No,No,No,No,No,No,No,No,No,No,No,No,No,No,No,No -Type:,Data (text),Data,Data,Select,Check,Data,Data,Check,Select,Date,Select,Password,Select,Select,Small Text,Small Text,Int,Int,Data,Read Only,Read Only -Info:,,,,"One of: System User, Website User",0 or 1,,,0 or 1,"One of: العربية, Deutsch, english, español, français, हिंदी, Hrvatski, nederlands, português, português brasileiro, српски, தமிழ், ไทย",,"One of: Male, Female, Other",,One of: attach_files:,One of: attach_files:,,,Integer,Integer,,, -Start entering data below this line,,,,,,,,,,,,,,,,,,,,, -,,DikmanShervashidze@armyspy.com,Dikman,System User,1,V,Shervashidze,0,,,,testpass,,,,,,,,, -,,Zukutakitoteka@teleworm.us,Zukutakitoteka,System User,1,,,0,,,,testpass,,,,,,,,, -,,HatsueKashiwagi@cuvox.de,Hatsue,System User,1,H,Kashiwagi,0,,,,testpass,,,,,,,,, -,,NuranVerkleij@einrot.com,Nuran,System User,1,T,Verkleij,0,,,,testpass,,,,,,,,, -,,aromn@armyspy.com,Дмитрий,System User,1,З,Пирогов,0,,,,testpass,,,,,,,,, -,,TildeLindqvist@cuvox.de,Tilde,System User,1,T,Lindqvist,0,,,,testpass,,,,,,,,, -,,MichalSobczak@teleworm.us,Michał,System User,1,S,Sobczak,0,,,,testpass,,,,,,,,, -,,GabrielleLoftus@superrito.com,Gabrielle,System User,1,J,Loftus,0,,,,testpass,,,,,,,,, -,,VakhitaRyzaev@teleworm.us,Vakhita,System User,1,A,Ryzaev,0,,,,testpass,,,,,,,,, -,,CharmaineGaudreau@cuvox.de,Charmaine,System User,1,D,Gaudreau,0,,,,testpass,,,,,,,,, -,,RafaelaMaartens@cuvox.de,Rafaëla,System User,1,Z,Maartens,0,,,,testpass,,,,,,,,, -,,NuguseYohannes@dayrep.com,Nuguse,System User,0,S,Yohannes,0,,,,testpass,,,,,,,,, -,,panca@armyspy.com,Раиса,System User,0,В,Белякова,0,,,,testpass,,,,,,,,, -,,CaYinLong@gustr.com,胤隆,System User,1,婷,蔡,0,,,,testpass,,,,,,,,, -,,FreddieScott@armyspy.com,Freddie,System User,1,A,Scott,0,,,,testpass,,,,,,,,, -,,BergoraVigfusdottir@superrito.com,Bergþóra,System User,1,Ö,Vigfúsdóttir,0,,,,testpass,,,,,,,,, -,,WardNajmalDinKalb@cuvox.de,Ward,System User,1,N,Kalb,0,,,,testpass,,,,,,,,, -,,WanMai@teleworm.us,Wan,System User,1,A,Mai,0,,,,testpass,,,,,,,,, -,,LeonAbdulov@superrito.com,Leon,System User,1,A,Abdulov,0,,,,testpass,,,,,,,,, -,,SabinaNovotna@superrito.com,Sabina,System User,1,J,Novotná,0,,,,testpass,,,,,,,,, \ No newline at end of file +Data Import Template,,,,,,,,,,,,,,,,,,,, +Table:,Profile,,,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,,,,, +Notes:,,,,,,,,,,,,,,,,,,,, +Please do not change the template headings.,,,,,,,,,,,,,,,,,,,, +First data column must be blank.,,,,,,,,,,,,,,,,,,,, +"If you are uploading new records, leave the ""name"" (ID) column blank.",,,,,,,,,,,,,,,,,,,, +"If you are uploading new records, ""Naming Series"" becomes mandatory, if present.",,,,,,,,,,,,,,,,,,,, +Only mandatory fields are necessary for new records. You can delete non-mandatory columns if you wish.,,,,,,,,,,,,,,,,,,,, +"For updating, you can update only selective columns.",,,,,,,,,,,,,,,,,,,, +You can only upload upto 5000 records in one go. (may be less in some cases),,,,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,,,,, +DocType:,Profile,,,,,,,,,,,,,,,,,,, +Column Labels:,ID,Email,First Name,User Type,Enabled,Middle Name (Optional),Last Name,Language,Birth Date,Gender,New Password,User Image,Background Image,Bio,Email Signature,Login After,Login Before,Restrict IP,Last Login,Last IP +Column Name:,name,email,first_name,user_type,enabled,middle_name,last_name,language,birth_date,gender,new_password,user_image,background_image,bio,email_signature,login_after,login_before,restrict_ip,last_login,last_ip +Mandatory:,Yes,Yes,Yes,Yes,No,No,No,No,No,No,No,No,No,No,No,No,No,No,No,No +Type:,Data (text),Data,Data,Select,Check,Data,Data,Select,Date,Select,Password,Select,Select,Small Text,Small Text,Int,Int,Data,Read Only,Read Only +Info:,,,,"One of: System User, Website User",0 or 1,,,"One of: العربية, Deutsch, english, español, français, हिंदी, Hrvatski, nederlands, português, português brasileiro, српски, தமிழ், ไทย",,"One of: Male, Female, Other",,One of: attach_files:,One of: attach_files:,,,Integer,Integer,,, +Start entering data below this line,,,,,,,,,,,,,,,,,,,, +,,DikmanShervashidze@armyspy.com,Dikman,System User,1,V,Shervashidze,,,,testpass,,,,,,,,, +,,Zukutakitoteka@teleworm.us,Zukutakitoteka,System User,1,,,,,,testpass,,,,,,,,, +,,HatsueKashiwagi@cuvox.de,Hatsue,System User,1,H,Kashiwagi,,,,testpass,,,,,,,,, +,,NuranVerkleij@einrot.com,Nuran,System User,1,T,Verkleij,,,,testpass,,,,,,,,, +,,aromn@armyspy.com,Дмитрий,System User,1,З,Пирогов,,,,testpass,,,,,,,,, +,,TildeLindqvist@cuvox.de,Tilde,System User,1,T,Lindqvist,,,,testpass,,,,,,,,, +,,MichalSobczak@teleworm.us,Michał,System User,1,S,Sobczak,,,,testpass,,,,,,,,, +,,GabrielleLoftus@superrito.com,Gabrielle,System User,1,J,Loftus,,,,testpass,,,,,,,,, +,,VakhitaRyzaev@teleworm.us,Vakhita,System User,1,A,Ryzaev,,,,testpass,,,,,,,,, +,,CharmaineGaudreau@cuvox.de,Charmaine,System User,1,D,Gaudreau,,,,testpass,,,,,,,,, +,,RafaelaMaartens@cuvox.de,Rafaëla,System User,1,Z,Maartens,,,,testpass,,,,,,,,, +,,NuguseYohannes@dayrep.com,Nuguse,System User,0,S,Yohannes,,,,testpass,,,,,,,,, +,,panca@armyspy.com,Раиса,System User,0,В,Белякова,,,,testpass,,,,,,,,, +,,CaYinLong@gustr.com,胤隆,System User,1,婷,蔡,,,,testpass,,,,,,,,, +,,FreddieScott@armyspy.com,Freddie,System User,1,A,Scott,,,,testpass,,,,,,,,, +,,BergoraVigfusdottir@superrito.com,Bergþóra,System User,1,Ö,Vigfúsdóttir,,,,testpass,,,,,,,,, +,,WardNajmalDinKalb@cuvox.de,Ward,System User,1,N,Kalb,,,,testpass,,,,,,,,, +,,WanMai@teleworm.us,Wan,System User,1,A,Mai,,,,testpass,,,,,,,,, +,,LeonAbdulov@superrito.com,Leon,System User,1,A,Abdulov,,,,testpass,,,,,,,,, +,,SabinaNovotna@superrito.com,Sabina,System User,1,J,Novotná,,,,testpass,,,,,,,,, diff --git a/utilities/demo/make_erpnext_demo.py b/utilities/demo/make_erpnext_demo.py index 70e7322ea83..6426367a951 100644 --- a/utilities/demo/make_erpnext_demo.py +++ b/utilities/demo/make_erpnext_demo.py @@ -42,7 +42,6 @@ def make_demo_user(): p.doc.last_name = "User" p.doc.enabled = 1 p.doc.user_type = "ERPNext Demo" - # p.doc.send_invite_email = 0 p.doc.new_password = "demo" p.insert() add_roles(p) @@ -58,7 +57,6 @@ def make_demo_user(): p.doc.last_name = "User" p.doc.enabled = 1 p.doc.user_type = "System User" - p.doc.send_invite_email = 0 p.doc.new_password = "admin010123" p.insert() roles.append("System Manager") From 1e15fe1ade79f376cc5aa2b17b59d59bbbdda8cf Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Mon, 23 Sep 2013 16:07:42 +0530 Subject: [PATCH 008/200] [fix] [minor] toggle display warehouse column based on update_stock --- accounts/doctype/sales_invoice/sales_invoice.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/accounts/doctype/sales_invoice/sales_invoice.js b/accounts/doctype/sales_invoice/sales_invoice.js index 60f73b5a191..0aa85e2ae8d 100644 --- a/accounts/doctype/sales_invoice/sales_invoice.js +++ b/accounts/doctype/sales_invoice/sales_invoice.js @@ -256,7 +256,6 @@ cur_frm.cscript.hide_fields = function(doc) { 'total_commission', 'advances']; item_flds_normal = ['sales_order', 'delivery_note'] - item_flds_pos = ['serial_no', 'batch_no', 'actual_qty', 'expense_account'] if(cint(doc.is_pos) == 1) { hide_field(par_flds); @@ -271,7 +270,9 @@ cur_frm.cscript.hide_fields = function(doc) { cur_frm.fields_dict['entries'].grid.set_column_disp(item_flds_normal, true); } - cur_frm.fields_dict['entries'].grid.set_column_disp(item_flds_pos, (cint(doc.update_stock)==1?true:false)); + item_flds_stock = ['serial_no', 'batch_no', 'actual_qty', 'expense_account', 'warehouse'] + cur_frm.fields_dict['entries'].grid.set_column_disp(item_flds_stock, + (cint(doc.update_stock)==1 ? true : false)); // India related fields var cp = wn.control_panel; From ac030a57c2fc568563f070c572dda1834f66a7b9 Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Mon, 23 Sep 2013 16:27:18 +0530 Subject: [PATCH 009/200] [minor] [cleanup] removed banner from lead --- selling/doctype/lead/lead.js | 9 --------- 1 file changed, 9 deletions(-) diff --git a/selling/doctype/lead/lead.js b/selling/doctype/lead/lead.js index a3ae7838672..aadc091da97 100644 --- a/selling/doctype/lead/lead.js +++ b/selling/doctype/lead/lead.js @@ -34,15 +34,6 @@ erpnext.LeadController = wn.ui.form.Controller.extend({ erpnext.hide_naming_series(); this.frm.clear_custom_buttons(); - this.frm.dashboard.reset(doc); - if(!doc.__islocal) { - if(doc.status=="Converted") { - this.frm.dashboard.set_headline_alert(wn._("Converted"), "alert-success", "icon-ok-sign"); - } else { - this.frm.dashboard.set_headline_alert(wn._(doc.status), "alert-info", "icon-exclamation-sign"); - } - } - this.frm.__is_customer = this.frm.__is_customer || this.frm.doc.__is_customer; if(!this.frm.doc.__islocal && !this.frm.__is_customer) { this.frm.add_custom_button("Create Customer", this.create_customer); From be68542bab85e3e0aaf7c4ea7fc04197777b2faf Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Mon, 23 Sep 2013 18:34:13 +0530 Subject: [PATCH 010/200] [minor] fetch debit/credit based on against JV --- .../journal_voucher/journal_voucher.js | 62 +++++++++++++------ .../journal_voucher/journal_voucher.py | 38 +++++++++--- .../doctype/support_ticket/support_ticket.js | 4 +- 3 files changed, 74 insertions(+), 30 deletions(-) diff --git a/accounts/doctype/journal_voucher/journal_voucher.js b/accounts/doctype/journal_voucher/journal_voucher.js index a3aa6f127a0..a6aa007b129 100644 --- a/accounts/doctype/journal_voucher/journal_voucher.js +++ b/accounts/doctype/journal_voucher/journal_voucher.js @@ -59,6 +59,50 @@ erpnext.accounts.JournalVoucher = wn.ui.form.Controller.extend({ }; }); }, + + against_voucher: function(doc, cdt, cdn) { + var d = wn.model.get_doc(cdt, cdn); + if (d.against_voucher && !flt(d.debit)) { + this.get_outstanding({ + 'doctype': 'Purchase Invoice', + 'docname': d.against_voucher + }, d) + } + }, + + against_invoice: function(doc, cdt, cdn) { + var d = wn.model.get_doc(cdt, cdn); + if (d.against_invoice && !flt(d.credit)) { + this.get_outstanding({ + 'doctype': 'Sales Invoice', + 'docname': d.against_invoice + }, d) + } + }, + + against_jv: function(doc, cdt, cdn) { + var d = wn.model.get_doc(cdt, cdn); + if (d.against_jv && !flt(d.credit) && !flt(d.debit)) { + this.get_outstanding({ + 'doctype': 'Journal Voucher', + 'docname': d.against_jv, + 'account': d.account + }, d) + } + }, + + get_outstanding: function(args, child) { + var me = this; + return this.frm.call({ + child: child, + method: "get_outstanding", + args: { args: args}, + callback: function(r) { + cur_frm.cscript.update_totals(me.frm.doc); + } + }); + } + }); cur_frm.script_manager.make(erpnext.accounts.JournalVoucher); @@ -88,24 +132,6 @@ cur_frm.cscript.is_opening = function(doc, cdt, cdn) { if (doc.is_opening == 'Yes') unhide_field('aging_date'); } -cur_frm.cscript.against_voucher = function(doc,cdt,cdn) { - var d = locals[cdt][cdn]; - if (d.against_voucher && !flt(d.debit)) { - args = {'doctype': 'Purchase Invoice', 'docname': d.against_voucher } - return get_server_fields('get_outstanding',docstring(args),'entries',doc,cdt,cdn,1,function(r,rt) { cur_frm.cscript.update_totals(doc); }); - } -} - -cur_frm.cscript.against_invoice = function(doc,cdt,cdn) { - var d = locals[cdt][cdn]; - if (d.against_invoice && !flt(d.credit)) { - args = {'doctype': 'Sales Invoice', 'docname': d.against_invoice } - return get_server_fields('get_outstanding',docstring(args),'entries',doc,cdt,cdn,1,function(r,rt) { cur_frm.cscript.update_totals(doc); }); - } -} - -// Update Totals - cur_frm.cscript.update_totals = function(doc) { var td=0.0; var tc =0.0; var el = getchildren('Journal Voucher Detail', doc.name, 'entries'); diff --git a/accounts/doctype/journal_voucher/journal_voucher.py b/accounts/doctype/journal_voucher/journal_voucher.py index a43f8ca7a58..a87166c3c28 100644 --- a/accounts/doctype/journal_voucher/journal_voucher.py +++ b/accounts/doctype/journal_voucher/journal_voucher.py @@ -260,15 +260,6 @@ class DocType(AccountsController): if gl_map: make_gl_entries(gl_map, cancel=cancel, adv_adj=adv_adj) - def get_outstanding(self, args): - args = eval(args) - o_s = webnotes.conn.sql("""select outstanding_amount from `tab%s` where name = %s""" % - (args['doctype'], '%s'), args['docname']) - if args['doctype'] == 'Purchase Invoice': - return {'debit': o_s and flt(o_s[0][0]) or 0} - if args['doctype'] == 'Sales Invoice': - return {'credit': o_s and flt(o_s[0][0]) or 0} - def get_balance(self): if not getlist(self.doclist,'entries'): msgprint("Please enter atleast 1 entry in 'GL Entries' table") @@ -434,4 +425,31 @@ def get_against_jv(doctype, txt, searchfield, start, page_len, filters): where jv_detail.parent = jv.name and jv_detail.account = %s and jv.docstatus = 1 and jv.%s like %s order by jv.name desc limit %s, %s""" % ("%s", searchfield, "%s", "%s", "%s"), - (filters["account"], "%%%s%%" % txt, start, page_len)) \ No newline at end of file + (filters["account"], "%%%s%%" % txt, start, page_len)) + +@webnotes.whitelist() +def get_outstanding(args): + args = eval(args) + if args.get("doctype") == "Journal Voucher" and args.get("account"): + against_jv_amount = webnotes.conn.sql(""" + select sum(ifnull(debit, 0)) - sum(ifnull(credit, 0)) + from `tabJournal Voucher Detail` where parent=%s and account=%s + and ifnull(against_invoice, '')='' and ifnull(against_voucher, '')='' + and ifnull(against_jv, '')=''""", (args['docname'], args['account'])) + + against_jv_amount = flt(against_jv_amount[0][0]) if against_jv_amount else 0 + if against_jv_amount > 0: + return {"credit": against_jv_amount} + else: + return {"debit": -1* against_jv_amount} + + elif args.get("doctype") == "Sales Invoice": + return { + "credit": flt(webnotes.conn.get_value("Sales Invoice", args["docname"], + "outstanding_amount")) + } + elif args.get("doctype") == "Purchase Invoice": + return { + "debit": flt(webnotes.conn.get_value("Purchase Invoice", args["docname"], + "outstanding_amount")) + } \ No newline at end of file diff --git a/support/doctype/support_ticket/support_ticket.js b/support/doctype/support_ticket/support_ticket.js index 0e612734393..c61d9732f87 100644 --- a/support/doctype/support_ticket/support_ticket.js +++ b/support/doctype/support_ticket/support_ticket.js @@ -6,7 +6,7 @@ cur_frm.fields_dict.customer.get_query = function(doc,cdt,cdn) { wn.provide("erpnext.support"); // TODO commonify this code -erpnext.support.CustomerIssue = wn.ui.form.Controller.extend({ +erpnext.support.SupportTicket = wn.ui.form.Controller.extend({ customer: function() { var me = this; if(this.frm.doc.customer) { @@ -18,7 +18,7 @@ erpnext.support.CustomerIssue = wn.ui.form.Controller.extend({ } }); -$.extend(cur_frm.cscript, new erpnext.support.CustomerIssue({frm: cur_frm})); +$.extend(cur_frm.cscript, new erpnext.support.SupportTicket({frm: cur_frm})); $.extend(cur_frm.cscript, { onload: function(doc, dt, dn) { From 517b30a11de6ef661ad62aa3332d0fb76e563d57 Mon Sep 17 00:00:00 2001 From: Pratik Vyas Date: Tue, 24 Sep 2013 12:29:35 +0530 Subject: [PATCH 011/200] fix for new wnf path stuff --- patches/april_2013/p05_update_file_data.py | 2 +- patches/april_2013/p06_update_file_size.py | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/patches/april_2013/p05_update_file_data.py b/patches/april_2013/p05_update_file_data.py index e03abc6b65c..664f9a4a0d5 100644 --- a/patches/april_2013/p05_update_file_data.py +++ b/patches/april_2013/p05_update_file_data.py @@ -52,7 +52,7 @@ def update_for_doc(doctype, doc): exists = True if not (filename.startswith("http://") or filename.startswith("https://")): - if not os.path.exists(webnotes.utils.get_path("public", "files", filename)): + if not os.path.exists(webnotes.utils.get_storage_path(webnotes.conf.files_path, filename)): exists = False if exists: diff --git a/patches/april_2013/p06_update_file_size.py b/patches/april_2013/p06_update_file_size.py index 6879625ad9d..be8c4009157 100644 --- a/patches/april_2013/p06_update_file_size.py +++ b/patches/april_2013/p06_update_file_size.py @@ -4,7 +4,7 @@ import webnotes, os, webnotes.utils def execute(): - files_path = webnotes.utils.get_path("public", "files") + files_path = webnotes.utils.get_storage_path(webnotes.conf.files_path) webnotes.conn.auto_commit_on_many_writes = 1 for f in webnotes.conn.sql("""select name, file_name from @@ -14,4 +14,4 @@ def execute(): if os.path.exists(filepath): webnotes.conn.set_value("File Data", f.name, "file_size", os.stat(filepath).st_size) - webnotes.conn.auto_commit_on_many_writes = 0 \ No newline at end of file + webnotes.conn.auto_commit_on_many_writes = 0 From de8b6aadafbde05ac5a56d199c083e599068aead Mon Sep 17 00:00:00 2001 From: Anand Doshi Date: Tue, 24 Sep 2013 17:17:39 +0530 Subject: [PATCH 012/200] [minor] fixes for import conf --- portal/templates/pages/profile.py | 2 +- selling/utils/cart.py | 6 +++--- setup/doctype/backup_manager/backup_googledrive.py | 2 +- setup/doctype/email_digest/email_digest.py | 2 +- startup/boot.py | 2 +- startup/event_handlers.py | 4 ++-- support/doctype/newsletter/newsletter.py | 2 +- utilities/demo/demo_control_panel.py | 2 +- utilities/demo/make_demo.py | 6 +++++- utilities/demo/make_erpnext_demo.py | 4 ++-- 10 files changed, 18 insertions(+), 14 deletions(-) diff --git a/portal/templates/pages/profile.py b/portal/templates/pages/profile.py index 8edd830d471..3d6a86f9cc6 100644 --- a/portal/templates/pages/profile.py +++ b/portal/templates/pages/profile.py @@ -33,7 +33,7 @@ def update_profile(fullname, password=None, company_name=None, mobile_no=None, p return _("Name is required") webnotes.conn.set_value("Profile", webnotes.session.user, "first_name", fullname) - webnotes.add_cookies["full_name"] = fullname + webnotes._response.set_cookie("full_name", fullname) return _("Updated") \ No newline at end of file diff --git a/selling/utils/cart.py b/selling/utils/cart.py index fc7d062d0d8..92d37ea969e 100644 --- a/selling/utils/cart.py +++ b/selling/utils/cart.py @@ -12,8 +12,8 @@ class WebsitePriceListMissingError(webnotes.ValidationError): pass def set_cart_count(quotation=None): if not quotation: quotation = _get_cart_quotation() - webnotes.add_cookies["cart_count"] = cstr(len(quotation.doclist.get( - {"parentfield": "quotation_details"})) or "") + cart_count = cstr(len(quotation.doclist.get({"parentfield": "quotation_details"}))) + webnotes._response.set_cookie("cart_count", cart_count) @webnotes.whitelist() def get_cart_quotation(doclist=None): @@ -47,7 +47,7 @@ def place_order(): sales_order.ignore_permissions = True sales_order.insert() sales_order.submit() - webnotes.add_cookies["cart_count"] = "" + webnotes._response.set_cookie("cart_count", "") return sales_order.doc.name diff --git a/setup/doctype/backup_manager/backup_googledrive.py b/setup/doctype/backup_manager/backup_googledrive.py index ee795186da5..daf852c4254 100644 --- a/setup/doctype/backup_manager/backup_googledrive.py +++ b/setup/doctype/backup_manager/backup_googledrive.py @@ -115,7 +115,7 @@ def get_gdrive_flow(): from oauth2client.client import OAuth2WebServerFlow from webnotes import conf - if not hasattr(conf, "gdrive_client_id"): + if not "gdrive_client_id" in conf: webnotes.msgprint(_("Please set Google Drive access keys in") + " conf.py", raise_exception=True) diff --git a/setup/doctype/email_digest/email_digest.py b/setup/doctype/email_digest/email_digest.py index 2a9acaa8b92..a05bae98963 100644 --- a/setup/doctype/email_digest/email_digest.py +++ b/setup/doctype/email_digest/email_digest.py @@ -458,7 +458,7 @@ def send(): now_date = now_datetime().date() from webnotes import conf - if hasattr(conf, "expires_on") and now_date > getdate(conf.expires_on): + if "expires_on" in conf and now_date > getdate(conf.expires_on): # do not send email digests to expired accounts return diff --git a/startup/boot.py b/startup/boot.py index 20887f720c6..d27c0b73e39 100644 --- a/startup/boot.py +++ b/startup/boot.py @@ -34,7 +34,7 @@ def boot_session(bootinfo): # load subscription info from webnotes import conf for key in ['max_users', 'expires_on', 'max_space', 'status', 'commercial_support']: - if hasattr(conf, key): bootinfo[key] = getattr(conf, key) + if key in conf: bootinfo[key] = conf.get(key) bootinfo['docs'] += webnotes.conn.sql("""select name, default_currency, cost_center from `tabCompany`""", as_dict=1, update={"doctype":":Company"}) diff --git a/startup/event_handlers.py b/startup/event_handlers.py index a333857b1b2..fc95414baf8 100644 --- a/startup/event_handlers.py +++ b/startup/event_handlers.py @@ -35,13 +35,13 @@ def on_login_post_session(login_manager): set_cart_count() def on_logout(login_manager): - webnotes.add_cookies["cart_count"] = "" + webnotes._response.set_cookie("cart_count", "") def check_if_expired(): """check if account is expired. If expired, do not allow login""" from webnotes import conf # check if expires_on is specified - if not hasattr(conf, 'expires_on'): return + if not 'expires_on' in conf: return # check if expired from datetime import datetime, date diff --git a/support/doctype/newsletter/newsletter.py b/support/doctype/newsletter/newsletter.py index 13ad47a0d8e..a6b5aa29e8a 100644 --- a/support/doctype/newsletter/newsletter.py +++ b/support/doctype/newsletter/newsletter.py @@ -91,7 +91,7 @@ class DocType(): raise_exception=1) from webnotes import conf - if getattr(conf, "status", None) == "Trial": + if (conf.get("status") or None) == "Trial": webnotes.msgprint(_("""Sending newsletters is not allowed for Trial users, \ to prevent abuse of this feature."""), raise_exception=1) diff --git a/utilities/demo/demo_control_panel.py b/utilities/demo/demo_control_panel.py index 1da690245ca..3123f41e089 100644 --- a/utilities/demo/demo_control_panel.py +++ b/utilities/demo/demo_control_panel.py @@ -2,7 +2,7 @@ def on_login(self): from webnotes.utils import validate_email_add from webnotes import conf - if hasattr(conf, "demo_notify_url"): + if "demo_notify_url" in conf: if webnotes.form_dict.lead_email and validate_email_add(webnotes.form_dict.lead_email): import requests response = requests.post(conf.demo_notify_url, data={ diff --git a/utilities/demo/make_demo.py b/utilities/demo/make_demo.py index 883186791a9..99bc018394c 100644 --- a/utilities/demo/make_demo.py +++ b/utilities/demo/make_demo.py @@ -36,11 +36,15 @@ def make(reset=False, simulate=True): if reset: setup() + else: + webnotes.connect() + if simulate: _simulate() - + def setup(): install() + webnotes.connect() complete_setup() make_customers_suppliers_contacts() make_items() diff --git a/utilities/demo/make_erpnext_demo.py b/utilities/demo/make_erpnext_demo.py index 6426367a951..4a72e4b589a 100644 --- a/utilities/demo/make_erpnext_demo.py +++ b/utilities/demo/make_erpnext_demo.py @@ -5,9 +5,9 @@ if __name__=="__main__": import webnotes, os import utilities.demo.make_demo -def make_demo_app(): +def make_demo_app(site=None): webnotes.mute_emails = 1 - webnotes.connect() + webnotes.connect(site) utilities.demo.make_demo.make(reset=True, simulate=False) # setup demo user etc so that the site it up faster, while the data loads make_demo_user() From a80f2e44315319fc3c3cbcaa7d14434ddf755da1 Mon Sep 17 00:00:00 2001 From: Pratik Vyas Date: Wed, 25 Sep 2013 12:40:33 +0530 Subject: [PATCH 013/200] refactor site_path --- patches/april_2013/p05_update_file_data.py | 2 +- patches/april_2013/p06_update_file_size.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/patches/april_2013/p05_update_file_data.py b/patches/april_2013/p05_update_file_data.py index 664f9a4a0d5..47d6de9186b 100644 --- a/patches/april_2013/p05_update_file_data.py +++ b/patches/april_2013/p05_update_file_data.py @@ -52,7 +52,7 @@ def update_for_doc(doctype, doc): exists = True if not (filename.startswith("http://") or filename.startswith("https://")): - if not os.path.exists(webnotes.utils.get_storage_path(webnotes.conf.files_path, filename)): + if not os.path.exists(webnotes.utils.get_site_path(webnotes.conf.files_path, filename)): exists = False if exists: diff --git a/patches/april_2013/p06_update_file_size.py b/patches/april_2013/p06_update_file_size.py index be8c4009157..973cea94d7e 100644 --- a/patches/april_2013/p06_update_file_size.py +++ b/patches/april_2013/p06_update_file_size.py @@ -4,7 +4,7 @@ import webnotes, os, webnotes.utils def execute(): - files_path = webnotes.utils.get_storage_path(webnotes.conf.files_path) + files_path = webnotes.utils.get_site_path(webnotes.conf.files_path) webnotes.conn.auto_commit_on_many_writes = 1 for f in webnotes.conn.sql("""select name, file_name from From f879a9dc2e8ceff2017ff5c0dd10d8e468dd232a Mon Sep 17 00:00:00 2001 From: Anand Doshi Date: Thu, 26 Sep 2013 15:56:54 +0530 Subject: [PATCH 014/200] [minor] wnf refactor, fixes in demo --- stock/doctype/warehouse/warehouse.py | 2 +- utilities/demo/make_demo.py | 16 +++++++++++----- utilities/demo/make_erpnext_demo.py | 8 ++++++-- 3 files changed, 18 insertions(+), 8 deletions(-) diff --git a/stock/doctype/warehouse/warehouse.py b/stock/doctype/warehouse/warehouse.py index 1494428549b..faf9b04e00e 100644 --- a/stock/doctype/warehouse/warehouse.py +++ b/stock/doctype/warehouse/warehouse.py @@ -31,7 +31,7 @@ class DocType: if not webnotes.conn.get_value("Account", {"account_type": "Warehouse", "master_name": self.doc.name}) and not webnotes.conn.get_value("Account", {"account_name": self.doc.warehouse_name}): - if self.doc.__islocal or not webnotes.conn.get_value("Stock Ledger Entry", + if self.doc.fields.get("__islocal") or not webnotes.conn.get_value("Stock Ledger Entry", {"warehouse": self.doc.name}): self.validate_parent_account() ac_bean = webnotes.bean({ diff --git a/utilities/demo/make_demo.py b/utilities/demo/make_demo.py index 2d2d07e0eaa..6c6ccab4df3 100644 --- a/utilities/demo/make_demo.py +++ b/utilities/demo/make_demo.py @@ -34,17 +34,20 @@ def make(reset=False, simulate=True): webnotes.mute_emails = True webnotes.rollback_on_exception = True + if not webnotes.conf.demo_db_name: + raise Exception("conf.py does not have demo_db_name") + if reset: setup() else: - webnotes.connect() + webnotes.connect(db_name=webnotes.conf.demo_db_name) if simulate: _simulate() def setup(): install() - webnotes.connect() + webnotes.connect(db_name=webnotes.conf.demo_db_name) complete_setup() make_customers_suppliers_contacts() make_items() @@ -142,14 +145,17 @@ def run_stock(current_date): # make purchase requests if can_make("Purchase Receipt"): from buying.doctype.purchase_order.purchase_order import make_purchase_receipt + from stock.stock_ledger import NegativeStockError report = "Purchase Order Items To Be Received" for po in list(set([r[0] for r in query_report.run(report)["result"] if r[0]!="Total"]))[:how_many("Purchase Receipt")]: pr = webnotes.bean(make_purchase_receipt(po)) pr.doc.posting_date = current_date pr.doc.fiscal_year = "2013" pr.insert() - pr.submit() - webnotes.conn.commit() + try: + pr.submit() + webnotes.conn.commit() + except NegativeStockError: pass # make delivery notes (if possible) if can_make("Delivery Note"): @@ -363,7 +369,7 @@ def install(): from webnotes.install_lib.install import Installer from webnotes import conf inst = Installer('root') - inst.import_from_db(conf.demo_db_name, verbose = 1) + inst.install(conf.demo_db_name, verbose=1, force=1) def complete_setup(): print "Complete Setup..." diff --git a/utilities/demo/make_erpnext_demo.py b/utilities/demo/make_erpnext_demo.py index 4a72e4b589a..50c66a3233a 100644 --- a/utilities/demo/make_erpnext_demo.py +++ b/utilities/demo/make_erpnext_demo.py @@ -7,7 +7,9 @@ import utilities.demo.make_demo def make_demo_app(site=None): webnotes.mute_emails = 1 - webnotes.connect(site) + webnotes.init(site=site) + webnotes.connect(db_name=webnotes.conf.demo_db_name, site=site) + utilities.demo.make_demo.make(reset=True, simulate=False) # setup demo user etc so that the site it up faster, while the data loads make_demo_user() @@ -116,4 +118,6 @@ def make_demo_on_login_script(): webnotes.conn.commit() if __name__=="__main__": - make_demo_app() + import sys + site = sys.argv[1:] + make_demo_app(site=site and site[0] or None) From c875300fe2c3aa6e52752b83d324d47d793b2198 Mon Sep 17 00:00:00 2001 From: Anand Doshi Date: Thu, 26 Sep 2013 17:54:51 +0530 Subject: [PATCH 015/200] [minor] moved wn-web.js and wn-web.css to memcache --- startup/event_handlers.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/startup/event_handlers.py b/startup/event_handlers.py index fc95414baf8..a0126118bb1 100644 --- a/startup/event_handlers.py +++ b/startup/event_handlers.py @@ -65,9 +65,6 @@ def check_if_expired(): raise webnotes.AuthenticationError def on_build(): - from website.doctype.website_settings.make_web_include_files import make - make() - from home.page.latest_updates import latest_updates latest_updates.make() From bc32535668642904c215ea1fbb1ea2f15d9a5e41 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A1rbara=20Perretti?= Date: Thu, 26 Sep 2013 18:18:22 -0300 Subject: [PATCH 016/200] Fixin translation in selling/page/selling_home/selling_home.js --- selling/page/selling_home/selling_home.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/selling/page/selling_home/selling_home.js b/selling/page/selling_home/selling_home.js index 9697ccf9855..cd8eb7225d5 100644 --- a/selling/page/selling_home/selling_home.js +++ b/selling/page/selling_home/selling_home.js @@ -63,7 +63,7 @@ wn.module_page["Selling"] = [ "label": wn._("Selling Settings"), "route": "Form/Selling Settings", "doctype":"Selling Settings", - "description": "Settings for Selling Module" + "description": wn.("Settings for Selling Module") }, { "route":"Form/Shopping Cart Settings", From dcec039da561e7e435299e861842ccf070e12f4e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A1rbara=20Perretti?= Date: Thu, 26 Sep 2013 18:24:15 -0300 Subject: [PATCH 017/200] Fixin translation in selling/page/sales_browser/sales_browser.js --- selling/page/sales_browser/sales_browser.js | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/selling/page/sales_browser/sales_browser.js b/selling/page/sales_browser/sales_browser.js index 53df1887b60..470fb688699 100644 --- a/selling/page/sales_browser/sales_browser.js +++ b/selling/page/sales_browser/sales_browser.js @@ -15,8 +15,9 @@ pscript['onload_Sales Browser'] = function(wrapper){ $(wrapper) .find(".layout-side-section") - .html('
Click on a link to get options to expand \ - get options Add / Edit / Delete.
') + .html('
'+ + wn._('Click on a link to get options to expand get options ') + + wn._('Add') + ' / ' + wn._('Edit') + ' / '+ wn._('Delete') + '.
') wrapper.make_tree = function() { var ctype = wn.get_route()[1] || 'Territory'; @@ -87,22 +88,22 @@ erpnext.SalesChart = Class.extend({ var node_links = []; if (wn.model.can_read(this.ctype)) { - node_links.push('Edit'); + node_links.push(''+wn._('Edit')+''); } if(data.expandable) { if (wn.boot.profile.can_create.indexOf(this.ctype) !== -1 || wn.boot.profile.in_create.indexOf(this.ctype) !== -1) { - node_links.push('Add Child'); + node_links.push('' + wn._('Add Child') + ''); } } if (wn.model.can_write(this.ctype)) { - node_links.push('Rename'); + node_links.push('' + wn._('Rename') + ''); }; if (wn.model.can_delete(this.ctype)) { - node_links.push('Delete'); + node_links.push('' + wn._('Delete') + ''); }; link.toolbar.append(node_links.join(" | ")); @@ -114,18 +115,18 @@ erpnext.SalesChart = Class.extend({ {fieldtype:'Data', fieldname: 'name_field', label:'New ' + me.ctype + ' Name', reqd:true}, {fieldtype:'Select', fieldname:'is_group', label:'Group Node', options:'No\nYes', - description: "Further nodes can be only created under 'Group' type nodes"}, + description: wn._("Further nodes can be only created under 'Group' type nodes")}, {fieldtype:'Button', fieldname:'create_new', label:'Create New' } ] if(me.ctype == "Sales Person") { fields.splice(-1, 0, {fieldtype:'Link', fieldname:'employee', label:'Employee', - options:'Employee', description: "Please enter Employee Id of this sales parson"}); + options:'Employee', description: wn._("Please enter Employee Id of this sales parson")}); } // the dialog var d = new wn.ui.Dialog({ - title:'New ' + me.ctype, + title: wn._('New ') + wn._(me.ctype), fields: fields }) From 629a032a7493bf4a4c1e11556d3aeb712b9cac6d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A1rbara=20Perretti?= Date: Thu, 26 Sep 2013 18:41:42 -0300 Subject: [PATCH 018/200] Fix translate Customer.js --- selling/doctype/customer/customer.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/selling/doctype/customer/customer.js b/selling/doctype/customer/customer.js index 4e2f42c7340..2b0e877360a 100644 --- a/selling/doctype/customer/customer.js +++ b/selling/doctype/customer/customer.js @@ -81,7 +81,7 @@ cur_frm.cscript.make_address = function() { return "select name, address_type, address_line1, address_line2, city, state, country, pincode, fax, email_id, phone, is_primary_address, is_shipping_address from tabAddress where customer='"+cur_frm.docname+"' and docstatus != 2 order by is_primary_address desc" }, as_dict: 1, - no_results_message: 'No addresses created', + no_results_message: wn._('No addresses created'), render_row: cur_frm.cscript.render_address_row, }); // note: render_address_row is defined in contact_control.js @@ -99,7 +99,7 @@ cur_frm.cscript.make_contact = function() { return "select name, first_name, last_name, email_id, phone, mobile_no, department, designation, is_primary_contact from tabContact where customer='"+cur_frm.docname+"' and docstatus != 2 order by is_primary_contact desc" }, as_dict: 1, - no_results_message: 'No contacts created', + no_results_message: wn._('No contacts created'), render_row: cur_frm.cscript.render_contact_row, }); // note: render_contact_row is defined in contact_control.js From dc3ab5c8deb1a69378ecb989ac8abd25b91c498c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A1rbara=20Perretti?= Date: Thu, 26 Sep 2013 19:12:31 -0300 Subject: [PATCH 019/200] Fixin translation in Opportunity.js --- selling/doctype/opportunity/opportunity.js | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/selling/doctype/opportunity/opportunity.js b/selling/doctype/opportunity/opportunity.js index 25f28bf3fbf..8b8fbf3866a 100644 --- a/selling/doctype/opportunity/opportunity.js +++ b/selling/doctype/opportunity/opportunity.js @@ -113,9 +113,9 @@ cur_frm.cscript.refresh = function(doc, cdt, cdn){ cur_frm.clear_custom_buttons(); if(doc.docstatus === 1 && doc.status!=="Opportunity Lost") { - cur_frm.add_custom_button('Create Quotation', cur_frm.cscript.create_quotation); - cur_frm.add_custom_button('Opportunity Lost', cur_frm.cscript['Declare Opportunity Lost']); - cur_frm.add_custom_button('Send SMS', cur_frm.cscript.send_sms); + cur_frm.add_custom_button( wn._('Create Quotation'), cur_frm.cscript.create_quotation); + cur_frm.add_custom_button(wn._('Opportunity Lost'), cur_frm.cscript['Declare Opportunity Lost']); + cur_frm.add_custom_button(wn._('Send SMS'), cur_frm.cscript.send_sms); } cur_frm.toggle_display("contact_info", doc.customer || doc.lead); @@ -181,11 +181,11 @@ cur_frm.cscript.lead = function(doc, cdt, cdn) { cur_frm.cscript['Declare Opportunity Lost'] = function(){ var dialog = new wn.ui.Dialog({ - title: "Set as Lost", + title: wn._("Set as Lost"), fields: [ - {"fieldtype": "Text", "label": "Reason for losing", "fieldname": "reason", + {"fieldtype": "Text", "label": wn._("Reason for losing"), "fieldname": "reason", "reqd": 1 }, - {"fieldtype": "Button", "label": "Update", "fieldname": "update"}, + {"fieldtype": "Button", "label": wn._("Update"), "fieldname": "update"}, ] }); @@ -198,7 +198,7 @@ cur_frm.cscript['Declare Opportunity Lost'] = function(){ args: args.reason, callback: function(r) { if(r.exc) { - msgprint("There were errors."); + msgprint(wn._("There were errors.")); return; } dialog.hide(); From 8db093b4c6dedc6f326c7bb786221a50006383e7 Mon Sep 17 00:00:00 2001 From: Anand Doshi Date: Fri, 27 Sep 2013 14:08:55 +0530 Subject: [PATCH 020/200] [minor] update password --- utilities/demo/make_demo.py | 1 + utilities/demo/make_erpnext_demo.py | 7 ++++--- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/utilities/demo/make_demo.py b/utilities/demo/make_demo.py index 6c6ccab4df3..4f30df62be3 100644 --- a/utilities/demo/make_demo.py +++ b/utilities/demo/make_demo.py @@ -40,6 +40,7 @@ def make(reset=False, simulate=True): if reset: setup() else: + webnotes.conn.close() webnotes.connect(db_name=webnotes.conf.demo_db_name) if simulate: diff --git a/utilities/demo/make_erpnext_demo.py b/utilities/demo/make_erpnext_demo.py index 50c66a3233a..a57441b556e 100644 --- a/utilities/demo/make_erpnext_demo.py +++ b/utilities/demo/make_erpnext_demo.py @@ -8,7 +8,6 @@ import utilities.demo.make_demo def make_demo_app(site=None): webnotes.mute_emails = 1 webnotes.init(site=site) - webnotes.connect(db_name=webnotes.conf.demo_db_name, site=site) utilities.demo.make_demo.make(reset=True, simulate=False) # setup demo user etc so that the site it up faster, while the data loads @@ -18,6 +17,8 @@ def make_demo_app(site=None): utilities.demo.make_demo.make(reset=False, simulate=True) def make_demo_user(): + from webnotes.auth import _update_password + roles = ["Accounts Manager", "Analytics", "Expense Approver", "Accounts User", "Leave Approver", "Blogger", "Customer", "Sales Manager", "Employee", "Support Manager", "HR Manager", "HR User", "Maintenance Manager", "Maintenance User", "Material Manager", @@ -44,10 +45,10 @@ def make_demo_user(): p.doc.last_name = "User" p.doc.enabled = 1 p.doc.user_type = "ERPNext Demo" - p.doc.new_password = "demo" p.insert() add_roles(p) p.save() + _update_password("demo@erpnext.com", "demo") # make system manager user if webnotes.conn.exists("Profile", "admin@erpnext.com"): @@ -59,11 +60,11 @@ def make_demo_user(): p.doc.last_name = "User" p.doc.enabled = 1 p.doc.user_type = "System User" - p.doc.new_password = "admin010123" p.insert() roles.append("System Manager") add_roles(p) p.save() + _update_password("admin@erpnext.com", "admin010123") # only read for newsletter webnotes.conn.sql("""update `tabDocPerm` set `write`=0, `create`=0, `cancel`=0 From 8e14a9cb93ffa468e63ee38fea9fb4175fa603fc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A1rbara=20Perretti?= Date: Fri, 27 Sep 2013 14:33:18 -0300 Subject: [PATCH 021/200] Fix translate Sales_Order.js --- selling/doctype/sales_order/sales_order.js | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/selling/doctype/sales_order/sales_order.js b/selling/doctype/sales_order/sales_order.js index 33699f05d84..b121f1503b3 100644 --- a/selling/doctype/sales_order/sales_order.js +++ b/selling/doctype/sales_order/sales_order.js @@ -26,34 +26,34 @@ erpnext.selling.SalesOrderController = erpnext.selling.SellingController.extend( cur_frm.dashboard.add_progress(cint(doc.per_billed) + wn._("% Billed"), doc.per_billed); - cur_frm.add_custom_button('Send SMS', cur_frm.cscript.send_sms); + cur_frm.add_custom_button(wn._('Send SMS'), cur_frm.cscript.send_sms); // delivery note if(flt(doc.per_delivered, 2) < 100 && doc.order_type=='Sales') - cur_frm.add_custom_button('Make Delivery', this.make_delivery_note); + cur_frm.add_custom_button(wn._('Make Delivery'), this.make_delivery_note); // maintenance if(flt(doc.per_delivered, 2) < 100 && (doc.order_type !='Sales')) { - cur_frm.add_custom_button('Make Maint. Visit', this.make_maintenance_visit); - cur_frm.add_custom_button('Make Maint. Schedule', + cur_frm.add_custom_button(wn._('Make Maint. Visit'), this.make_maintenance_visit); + cur_frm.add_custom_button(wn._('Make Maint. Schedule'), this.make_maintenance_schedule); } // indent if(!doc.order_type || (doc.order_type == 'Sales')) - cur_frm.add_custom_button('Make ' + wn._('Material Request'), + cur_frm.add_custom_button(wn._('Make ') + wn._('Material Request'), this.make_material_request); // sales invoice if(flt(doc.per_billed, 2) < 100) - cur_frm.add_custom_button('Make Invoice', this.make_sales_invoice); + cur_frm.add_custom_button(wn._('Make Invoice'), this.make_sales_invoice); // stop if(flt(doc.per_delivered, 2) < 100 || doc.per_billed < 100) - cur_frm.add_custom_button('Stop!', cur_frm.cscript['Stop Sales Order']); + cur_frm.add_custom_button(wn._('Stop!'), cur_frm.cscript['Stop Sales Order']); } else { // un-stop - cur_frm.dashboard.set_headline_alert("Stopped", "alert-danger", "icon-stop"); - cur_frm.add_custom_button('Unstop', cur_frm.cscript['Unstop Sales Order']); + cur_frm.dashboard.set_headline_alert(wn._("Stopped"), "alert-danger", "icon-stop"); + cur_frm.add_custom_button(wn._('Unstop'), cur_frm.cscript['Unstop Sales Order']); } } @@ -157,7 +157,7 @@ cur_frm.fields_dict['project_name'].get_query = function(doc, cdt, cdn) { cur_frm.cscript['Stop Sales Order'] = function() { var doc = cur_frm.doc; - var check = confirm("Are you sure you want to STOP " + doc.name); + var check = confirm(wn._("Are you sure you want to STOP ") + doc.name); if (check) { return $c('runserverobj', { @@ -172,7 +172,7 @@ cur_frm.cscript['Stop Sales Order'] = function() { cur_frm.cscript['Unstop Sales Order'] = function() { var doc = cur_frm.doc; - var check = confirm("Are you sure you want to UNSTOP " + doc.name); + var check = confirm(wn._("Are you sure you want to UNSTOP ") + doc.name); if (check) { return $c('runserverobj', { From 55fbeb9e9300c97444064eca15f790859cb90046 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A1rbara=20Perretti?= Date: Fri, 27 Sep 2013 14:40:54 -0300 Subject: [PATCH 022/200] Fix translate Lead.js --- selling/doctype/lead/lead.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/selling/doctype/lead/lead.js b/selling/doctype/lead/lead.js index 3c6fda7922c..28507fb326e 100644 --- a/selling/doctype/lead/lead.js +++ b/selling/doctype/lead/lead.js @@ -36,9 +36,9 @@ erpnext.LeadController = wn.ui.form.Controller.extend({ this.frm.__is_customer = this.frm.__is_customer || this.frm.doc.__is_customer; if(!this.frm.doc.__islocal && !this.frm.__is_customer) { - this.frm.add_custom_button("Create Customer", this.create_customer); - this.frm.add_custom_button("Create Opportunity", this.create_opportunity); - this.frm.add_custom_button("Send SMS", this.frm.cscript.send_sms); + this.frm.add_custom_button(wn._("Create Customer"), this.create_customer); + this.frm.add_custom_button(wn._("Create Opportunity"), this.create_opportunity); + this.frm.add_custom_button(wn._("Send SMS"), this.frm.cscript.send_sms); } cur_frm.communication_view = new wn.views.CommunicationList({ From 49ad416843802105c6e2502ff0c1ac46c595c300 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A1rbara=20Perretti?= Date: Fri, 27 Sep 2013 15:01:14 -0300 Subject: [PATCH 023/200] Fix translate Quotation.js --- selling/doctype/quotation/quotation.js | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/selling/doctype/quotation/quotation.js b/selling/doctype/quotation/quotation.js index ea1b62aa0a7..90be81a257f 100644 --- a/selling/doctype/quotation/quotation.js +++ b/selling/doctype/quotation/quotation.js @@ -34,11 +34,11 @@ erpnext.selling.QuotationController = erpnext.selling.SellingController.extend({ } if(doc.docstatus == 1 && doc.status!=='Order Lost') { - cur_frm.add_custom_button('Make Sales Order', cur_frm.cscript['Make Sales Order']); + cur_frm.add_custom_button(wn._('Make Sales Order'), cur_frm.cscript['Make Sales Order']); if(doc.status!=="Order Confirmed") { - cur_frm.add_custom_button('Set as Lost', cur_frm.cscript['Declare Order Lost']); + cur_frm.add_custom_button(wn._('Set as Lost'), cur_frm.cscript['Declare Order Lost']); } - cur_frm.add_custom_button('Send SMS', cur_frm.cscript.send_sms); + cur_frm.add_custom_button(wn._('Send SMS'), cur_frm.cscript.send_sms); } if (this.frm.doc.docstatus===0) { @@ -130,9 +130,9 @@ cur_frm.cscript['Declare Order Lost'] = function(){ var dialog = new wn.ui.Dialog({ title: "Set as Lost", fields: [ - {"fieldtype": "Text", "label": "Reason for losing", "fieldname": "reason", + {"fieldtype": "Text", "label": wn._("Reason for losing"), "fieldname": "reason", "reqd": 1 }, - {"fieldtype": "Button", "label": "Update", "fieldname": "update"}, + {"fieldtype": "Button", "label": wn._("Update"), "fieldname": "update"}, ] }); @@ -145,7 +145,7 @@ cur_frm.cscript['Declare Order Lost'] = function(){ args: args.reason, callback: function(r) { if(r.exc) { - msgprint("There were errors."); + msgprint(wn._("There were errors.")); return; } dialog.hide(); From 97bf1f79db44785e1e834d4e6a59353c5ff7fb4b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A1rbara=20Perretti?= Date: Fri, 27 Sep 2013 15:28:53 -0300 Subject: [PATCH 024/200] Fix translate Sales_bom.js --- selling/doctype/sales_bom/sales_bom.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/selling/doctype/sales_bom/sales_bom.js b/selling/doctype/sales_bom/sales_bom.js index 80e66b824d6..921d9d6683f 100644 --- a/selling/doctype/sales_bom/sales_bom.js +++ b/selling/doctype/sales_bom/sales_bom.js @@ -4,7 +4,7 @@ cur_frm.cscript.refresh = function(doc, cdt, cdn) { cur_frm.toggle_enable('new_item_code', doc.__islocal); if(!doc.__islocal) { - cur_frm.add_custom_button("Check for Duplicates", function() { + cur_frm.add_custom_button(wn._("Check for Duplicates"), function() { return cur_frm.call_server('check_duplicate', 1) }, 'icon-search') } @@ -15,8 +15,8 @@ cur_frm.fields_dict.new_item_code.get_query = function() { query: "selling.doctype.sales_bom.sales_bom.get_new_item_code" } } -cur_frm.fields_dict.new_item_code.query_description = 'Select Item where "Is Stock Item" is "No" \ - and "Is Sales Item" is "Yes" and there is no other Sales BOM'; +cur_frm.fields_dict.new_item_code.query_description = wn._('Select Item where "Is Stock Item" is "No"')+ wn._('\ + and "Is Sales Item" is "Yes" and there is no other Sales BOM'); cur_frm.cscript.item_code = function(doc, dt, dn) { var d = locals[dt][dn]; From 4098c2675f83e5ae99d0170ee638f7d5d2f4bd2a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A1rbara=20Perretti?= Date: Fri, 27 Sep 2013 17:05:17 -0300 Subject: [PATCH 025/200] Fix translate Sales_Common.js --- selling/doctype/sales_common/sales_common.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/selling/doctype/sales_common/sales_common.js b/selling/doctype/sales_common/sales_common.js index dc58377e4bf..20ba92a885a 100644 --- a/selling/doctype/sales_common/sales_common.js +++ b/selling/doctype/sales_common/sales_common.js @@ -70,7 +70,7 @@ erpnext.selling.SellingController = erpnext.TransactionController.extend({ this.frm.set_query("batch_no", this.fname, function(doc, cdt, cdn) { var item = wn.model.get_doc(cdt, cdn); if(!item.item_code) { - wn.throw("Please enter Item Code to get batch no"); + wn.throw(wn._("Please enter Item Code to get batch no")); } else { if(item.warehouse) { return { @@ -632,12 +632,12 @@ var set_sales_bom_help = function(doc) { $(cur_frm.fields_dict.packing_list.row.wrapper).toggle(true); if (inList(['Delivery Note', 'Sales Invoice'], doc.doctype)) { - help_msg = "
\ - For 'Sales BOM' items, warehouse, serial no and batch no \ + help_msg = "
" + + wn._("For 'Sales BOM' items, warehouse, serial no and batch no \ will be considered from the 'Packing List' table. \ If warehouse and batch no are same for all packing items for any 'Sales BOM' item, \ - those values can be entered in the main item table, values will be copied to 'Packing List' table. \ -
"; + those values can be entered in the main item table, values will be copied to 'Packing List' table.")+ + "
"; wn.meta.get_docfield(doc.doctype, 'sales_bom_help', doc.name).options = help_msg; } } else { From c5fe86c773ba5a6d61b22b36dba78dfd2059a696 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A1rbara=20Perretti?= Date: Fri, 27 Sep 2013 17:21:47 -0300 Subject: [PATCH 026/200] Fix Translate Sales_Analytics.js --- .../page/sales_analytics/sales_analytics.js | 34 +++++++++---------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/selling/page/sales_analytics/sales_analytics.js b/selling/page/sales_analytics/sales_analytics.js index 0159ae021c5..daa78b40d04 100644 --- a/selling/page/sales_analytics/sales_analytics.js +++ b/selling/page/sales_analytics/sales_analytics.js @@ -4,7 +4,7 @@ wn.pages['sales-analytics'].onload = function(wrapper) { wn.ui.make_app_page({ parent: wrapper, - title: 'Sales Analytics', + title: wn._('Sales Analytics'), single_column: true }); new erpnext.SalesAnalytics(wrapper); @@ -17,7 +17,7 @@ wn.pages['sales-analytics'].onload = function(wrapper) { erpnext.SalesAnalytics = wn.views.TreeGridReport.extend({ init: function(wrapper) { this._super({ - title: "Sales Analytics", + title: wn._("Sales Analytics"), page: wrapper, parent: $(wrapper).find('.layout-main'), appframe: wrapper.appframe, @@ -30,14 +30,14 @@ erpnext.SalesAnalytics = wn.views.TreeGridReport.extend({ this.tree_grids = { "Customer Group": { - label: "Customer Group / Customer", + label: wn._("Customer Group / Customer"), show: true, item_key: "customer", parent_field: "parent_customer_group", formatter: function(item) { return item.name; } }, "Customer": { - label: "Customer", + label: wn._("Customer"), show: false, item_key: "customer", formatter: function(item) { @@ -45,7 +45,7 @@ erpnext.SalesAnalytics = wn.views.TreeGridReport.extend({ } }, "Item Group": { - label: "Item", + label: wn._("Item"), show: true, parent_field: "parent_item_group", item_key: "item_code", @@ -54,7 +54,7 @@ erpnext.SalesAnalytics = wn.views.TreeGridReport.extend({ } }, "Item": { - label: "Item", + label: wn._("Item"), show: false, item_key: "item_code", formatter: function(item) { @@ -62,7 +62,7 @@ erpnext.SalesAnalytics = wn.views.TreeGridReport.extend({ } }, "Territory": { - label: "Territory / Customer", + label: wn._("Territory / Customer"), show: true, item_key: "customer", parent_field: "parent_territory", @@ -88,23 +88,23 @@ erpnext.SalesAnalytics = wn.views.TreeGridReport.extend({ this.columns = std_columns.concat(this.columns); }, filters: [ - {fieldtype:"Select", label: "Tree Type", options:["Customer Group", "Customer", + {fieldtype:"Select", label: wn._("Tree Type"), options:["Customer Group", "Customer", "Item Group", "Item", "Territory"], filter: function(val, item, opts, me) { return me.apply_zero_filter(val, item, opts, me); }}, - {fieldtype:"Select", label: "Based On", options:["Sales Invoice", + {fieldtype:"Select", label: wn._("Based On"), options:["Sales Invoice", "Sales Order", "Delivery Note"]}, - {fieldtype:"Select", label: "Value or Qty", options:["Value", "Quantity"]}, - {fieldtype:"Select", label: "Company", link:"Company", + {fieldtype:"Select", label: wn._("Value or Qty"), options:["Value", "Quantity"]}, + {fieldtype:"Select", label: wn._("Company"), link:"Company", default_value: "Select Company..."}, - {fieldtype:"Date", label: "From Date"}, - {fieldtype:"Label", label: "To"}, - {fieldtype:"Date", label: "To Date"}, - {fieldtype:"Select", label: "Range", + {fieldtype:"Date", label: wn._("From Date")}, + {fieldtype:"Label", label: wn._("To")}, + {fieldtype:"Date", label: wn._("To Date")}, + {fieldtype:"Select", label: wn._("Range"), options:["Daily", "Weekly", "Monthly", "Quarterly", "Yearly"]}, - {fieldtype:"Button", label: "Refresh", icon:"icon-refresh icon-white", cssClass:"btn-info"}, - {fieldtype:"Button", label: "Reset Filters"} + {fieldtype:"Button", label: wn._("Refresh"), icon:"icon-refresh icon-white", cssClass:"btn-info"}, + {fieldtype:"Button", label: wn._("Reset Filters")} ], setup_filters: function() { var me = this; From d25c46a4ed5c91a48a3bc8b249e8d00c4fd74cda Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A1rbara=20Perretti?= Date: Fri, 27 Sep 2013 17:51:05 -0300 Subject: [PATCH 027/200] Fix translate account.js --- accounts/doctype/account/account.js | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/accounts/doctype/account/account.js b/accounts/doctype/account/account.js index 9ccb16b1d98..67a46cda157 100644 --- a/accounts/doctype/account/account.js +++ b/accounts/doctype/account/account.js @@ -11,7 +11,7 @@ cur_frm.cscript.onload = function(doc, cdt, cdn) { // ----------------------------------------- cur_frm.cscript.refresh = function(doc, cdt, cdn) { if(doc.__islocal) { - msgprint("Please create new account from Chart of Accounts."); + msgprint(wn._("Please create new account from Chart of Accounts.")); throw "cannot create"; } @@ -38,7 +38,7 @@ cur_frm.cscript.refresh = function(doc, cdt, cdn) { // read-only for root accounts if(!doc.parent_account) { cur_frm.perm = [[1,0,0], [1,0,0]]; - cur_frm.set_intro("This is a root account and cannot be edited."); + cur_frm.set_intro(wn._("This is a root account and cannot be edited.")); } else { // credit days and type if customer or supplier cur_frm.set_intro(null); @@ -81,17 +81,17 @@ cur_frm.cscript.account_type = function(doc, cdt, cdn) { // Hide/unhide group or ledger // ----------------------------------------- cur_frm.cscript.add_toolbar_buttons = function(doc) { - cur_frm.add_custom_button('Chart of Accounts', + cur_frm.add_custom_button(wn._('Chart of Accounts'), function() { wn.set_route("Accounts Browser", "Account"); }, 'icon-sitemap') if (cstr(doc.group_or_ledger) == 'Group') { - cur_frm.add_custom_button('Convert to Ledger', + cur_frm.add_custom_button(wn._('Convert to Ledger'), function() { cur_frm.cscript.convert_to_ledger(); }, 'icon-retweet') } else if (cstr(doc.group_or_ledger) == 'Ledger') { - cur_frm.add_custom_button('Convert to Group', + cur_frm.add_custom_button(wn._('Convert to Group'), function() { cur_frm.cscript.convert_to_group(); }, 'icon-retweet') - cur_frm.add_custom_button('View Ledger', function() { + cur_frm.add_custom_button(wn._('View Ledger'), function() { wn.route_options = { "account": doc.name, "from_date": sys_defaults.year_start_date, From 14aedc92fb6665a66176493c9eab42ccac375e66 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A1rbara=20Perretti?= Date: Mon, 30 Sep 2013 13:56:28 -0300 Subject: [PATCH 028/200] Fix translate Cost_center.js --- accounts/doctype/cost_center/cost_center.js | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/accounts/doctype/cost_center/cost_center.js b/accounts/doctype/cost_center/cost_center.js index c3519bfc6c7..3308a1d9129 100644 --- a/accounts/doctype/cost_center/cost_center.js +++ b/accounts/doctype/cost_center/cost_center.js @@ -41,8 +41,8 @@ cur_frm.cscript.refresh = function(doc, cdt, cdn) { cur_frm.toggle_enable(['group_or_ledger', 'company'], doc.__islocal); if(!doc.__islocal && doc.group_or_ledger=='Group') { - intro_txt += '

Note: This Cost Center is a Group, \ - Accounting Entries are not allowed against groups.

'; + intro_txt += '

Note:'+ wn._('This Cost Center is a')+ ''+wn._('Group')+''+ wn._(', \ + Accounting Entries are not allowed against groups.')+'

'; } cur_frm.cscript.hide_unhide_group_ledger(doc); @@ -50,22 +50,22 @@ cur_frm.cscript.refresh = function(doc, cdt, cdn) { cur_frm.toggle_display('sb1', doc.group_or_ledger=='Ledger') cur_frm.set_intro(intro_txt); - cur_frm.add_custom_button('Chart of Cost Centers', + cur_frm.add_custom_button(wn._('Chart of Cost Centers'), function() { wn.set_route("Accounts Browser", "Cost Center"); }, 'icon-sitemap') } cur_frm.cscript.parent_cost_center = function(doc,cdt,cdn){ if(!doc.company){ - alert('Please enter company name first'); + alert(wn._('Please enter company name first')); } } cur_frm.cscript.hide_unhide_group_ledger = function(doc) { if (cstr(doc.group_or_ledger) == 'Group') { - cur_frm.add_custom_button('Convert to Ledger', + cur_frm.add_custom_button(wn._('Convert to Ledger'), function() { cur_frm.cscript.convert_to_ledger(); }, 'icon-retweet') } else if (cstr(doc.group_or_ledger) == 'Ledger') { - cur_frm.add_custom_button('Convert to Group', + cur_frm.add_custom_button(wn._('Convert to Group'), function() { cur_frm.cscript.convert_to_group(); }, 'icon-retweet') } } From 9fc8e88503104412e7ed34c12b232aa07489208a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A1rbara=20Perretti?= Date: Mon, 30 Sep 2013 14:33:13 -0300 Subject: [PATCH 029/200] Fix translate Fiscal_year.js --- accounts/doctype/fiscal_year/fiscal_year.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/accounts/doctype/fiscal_year/fiscal_year.js b/accounts/doctype/fiscal_year/fiscal_year.js index c5500aa1f37..ba63520e29f 100644 --- a/accounts/doctype/fiscal_year/fiscal_year.js +++ b/accounts/doctype/fiscal_year/fiscal_year.js @@ -5,8 +5,8 @@ cur_frm.cscript.refresh = function(doc, dt, dn) { cur_frm.toggle_enable('year_start_date', doc.__islocal) if (!doc.__islocal && (doc.name != sys_defaults.fiscal_year)) { - cur_frm.add_custom_button("Set as Default", cur_frm.cscript.set_as_default); - cur_frm.set_intro("To set this Fiscal Year as Deafult, click on 'Set as Default'"); + cur_frm.add_custom_button(wn._("Set as Default"), cur_frm.cscript.set_as_default); + cur_frm.set_intro(wn._("To set this Fiscal Year as Deafult, click on 'Set as Default'")); } else cur_frm.set_intro(""); } From 676e081ed38819d720a28946872fbda516496281 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A1rbara=20Perretti?= Date: Mon, 30 Sep 2013 14:36:00 -0300 Subject: [PATCH 030/200] Fix translate Cost_center.js --- accounts/doctype/cost_center/cost_center.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/accounts/doctype/cost_center/cost_center.js b/accounts/doctype/cost_center/cost_center.js index 3308a1d9129..9995b6b1b5c 100644 --- a/accounts/doctype/cost_center/cost_center.js +++ b/accounts/doctype/cost_center/cost_center.js @@ -41,8 +41,8 @@ cur_frm.cscript.refresh = function(doc, cdt, cdn) { cur_frm.toggle_enable(['group_or_ledger', 'company'], doc.__islocal); if(!doc.__islocal && doc.group_or_ledger=='Group') { - intro_txt += '

Note:'+ wn._('This Cost Center is a')+ ''+wn._('Group')+''+ wn._(', \ - Accounting Entries are not allowed against groups.')+'

'; + intro_txt += '

'+wn._('Note:')+''+ wn._('This Cost Center is a')+ ''+wn._('Group')+', '+ + wn._('Accounting Entries are not allowed against groups.')+'

'; } cur_frm.cscript.hide_unhide_group_ledger(doc); From dc6cab63dcdc40b583f383f5a826ae28c48a4e7e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A1rbara=20Perretti?= Date: Mon, 30 Sep 2013 15:03:17 -0300 Subject: [PATCH 031/200] Fix translate journal_voucher.js --- accounts/doctype/journal_voucher/journal_voucher.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/accounts/doctype/journal_voucher/journal_voucher.js b/accounts/doctype/journal_voucher/journal_voucher.js index a3aa6f127a0..644cec2960c 100644 --- a/accounts/doctype/journal_voucher/journal_voucher.js +++ b/accounts/doctype/journal_voucher/journal_voucher.js @@ -68,7 +68,7 @@ cur_frm.cscript.refresh = function(doc) { erpnext.hide_naming_series(); cur_frm.cscript.voucher_type(doc); if(doc.docstatus==1) { - cur_frm.add_custom_button('View Ledger', function() { + cur_frm.add_custom_button(wn._('View Ledger'), function() { wn.route_options = { "voucher_no": doc.name, "from_date": doc.posting_date, @@ -156,7 +156,7 @@ cur_frm.cscript.select_print_heading = function(doc,cdt,cdn){ cur_frm.pformat.print_heading = doc.select_print_heading; } else - cur_frm.pformat.print_heading = "Journal Voucher"; + cur_frm.pformat.print_heading = wn._("Journal Voucher"); } cur_frm.cscript.voucher_type = function(doc, cdt, cdn) { From 568ce8653edce9e5be8bae5b5a3514e440e72910 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A1rbara=20Perretti?= Date: Mon, 30 Sep 2013 15:13:24 -0300 Subject: [PATCH 032/200] Fix translate payment_to_invoice_matching_tool.js --- .../payment_to_invoice_matching_tool.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/accounts/doctype/payment_to_invoice_matching_tool/payment_to_invoice_matching_tool.js b/accounts/doctype/payment_to_invoice_matching_tool/payment_to_invoice_matching_tool.js index a48520cbd50..980d6e7d3c3 100644 --- a/accounts/doctype/payment_to_invoice_matching_tool/payment_to_invoice_matching_tool.js +++ b/accounts/doctype/payment_to_invoice_matching_tool/payment_to_invoice_matching_tool.js @@ -13,15 +13,15 @@ cur_frm.cscript.onload_post_render = function(doc) { cur_frm.cscript.refresh = function(doc) { cur_frm.set_intro(""); if(!doc.voucher_no) { - cur_frm.set_intro("Select the Invoice against which you want to allocate payments."); + cur_frm.set_intro(wn._("Select the Invoice against which you want to allocate payments.")); } else { - cur_frm.set_intro("Set allocated amount against each Payment Entry and click 'Allocate'."); + cur_frm.set_intro(wn._("Set allocated amount against each Payment Entry and click 'Allocate'.")); } } cur_frm.fields_dict.voucher_no.get_query = function(doc) { // TO-do: check for pos, it should not come - if (!doc.account) msgprint("Please select Account first"); + if (!doc.account) msgprint(wn._("Please select Account first")); else { return { doctype: doc.voucher_type, From 46d2b9a8959deda9a4df66c2fad27716afd2dffd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A1rbara=20Perretti?= Date: Mon, 30 Sep 2013 15:19:16 -0300 Subject: [PATCH 033/200] Fix translate purchase_invoice.js --- accounts/doctype/purchase_invoice/purchase_invoice.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/accounts/doctype/purchase_invoice/purchase_invoice.js b/accounts/doctype/purchase_invoice/purchase_invoice.js index 2428a7dae91..40e6433fbfe 100644 --- a/accounts/doctype/purchase_invoice/purchase_invoice.js +++ b/accounts/doctype/purchase_invoice/purchase_invoice.js @@ -26,10 +26,10 @@ erpnext.accounts.PurchaseInvoice = erpnext.buying.BuyingController.extend({ // Show / Hide button if(doc.docstatus==1 && doc.outstanding_amount > 0) - this.frm.add_custom_button('Make Payment Entry', this.make_bank_voucher); + this.frm.add_custom_button(wn._('Make Payment Entry'), this.make_bank_voucher); if(doc.docstatus==1) { - cur_frm.add_custom_button('View Ledger', function() { + cur_frm.add_custom_button(wn._('View Ledger'), function() { wn.route_options = { "voucher_no": doc.name, "from_date": doc.posting_date, @@ -213,5 +213,5 @@ cur_frm.cscript.select_print_heading = function(doc,cdt,cdn){ cur_frm.pformat.print_heading = doc.select_print_heading; } else - cur_frm.pformat.print_heading = "Purchase Invoice"; + cur_frm.pformat.print_heading = wn._("Purchase Invoice"); } \ No newline at end of file From 1a920c7ce8e95d3fc9bbbf26abf57f39c4da722a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A1rbara=20Perretti?= Date: Mon, 30 Sep 2013 15:35:08 -0300 Subject: [PATCH 034/200] Fix translate purchase_taxes_and_charges_master.js --- .../purchase_taxes_and_charges_master.js | 24 +++++++++---------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/accounts/doctype/purchase_taxes_and_charges_master/purchase_taxes_and_charges_master.js b/accounts/doctype/purchase_taxes_and_charges_master/purchase_taxes_and_charges_master.js index 423c4e49b9d..c8fdeaf4e43 100644 --- a/accounts/doctype/purchase_taxes_and_charges_master/purchase_taxes_and_charges_master.js +++ b/accounts/doctype/purchase_taxes_and_charges_master/purchase_taxes_and_charges_master.js @@ -60,12 +60,12 @@ cur_frm.pformat.purchase_tax_details= function(doc){ cur_frm.cscript.add_deduct_tax = function(doc, cdt, cdn) { var d = locals[cdt][cdn]; if(!d.category && d.add_deduct_tax){ - alert("Please select Category first"); + alert(wn._("Please select Category first")); d.add_deduct_tax = ''; } else if(d.category != 'Total' && d.add_deduct_tax == 'Deduct') { console.log([d.category, d.add_deduct_tax]); - msgprint("You cannot deduct when category is for 'Valuation' or 'Valuation and Total'"); + msgprint(wn._("You cannot deduct when category is for 'Valuation' or 'Valuation and Total'")); d.add_deduct_tax = ''; } @@ -74,15 +74,15 @@ cur_frm.cscript.add_deduct_tax = function(doc, cdt, cdn) { cur_frm.cscript.charge_type = function(doc, cdt, cdn) { var d = locals[cdt][cdn]; if(!d.category && d.charge_type){ - alert("Please select Category first"); + alert(wn._("Please select Category first")); d.charge_type = ''; } else if(d.idx == 1 && (d.charge_type == 'On Previous Row Amount' || d.charge_type == 'On Previous Row Total')){ - alert("You cannot select Charge Type as 'On Previous Row Amount' or 'On Previous Row Total' for first row"); + alert(wn._("You cannot select Charge Type as 'On Previous Row Amount' or 'On Previous Row Total' for first row")); d.charge_type = ''; } else if((d.category == 'Valuation' || d.category == 'Valuation and Total') && (d.charge_type == 'On Previous Row Amount' || d.charge_type == 'On Previous Row Total')){ - alert("You cannot select charge type as 'On Previous Row Amount' or 'On Previous Row Total' for valuation. You can select only 'Total' option for previous row amount or previous row total") + alert(wn._("You cannot select charge type as 'On Previous Row Amount' or 'On Previous Row Total' for valuation. You can select only 'Total' option for previous row amount or previous row total")) d.charge_type = ''; } validated = false; @@ -97,16 +97,16 @@ cur_frm.cscript.charge_type = function(doc, cdt, cdn) { cur_frm.cscript.row_id = function(doc, cdt, cdn) { var d = locals[cdt][cdn]; if(!d.charge_type && d.row_id){ - alert("Please select Charge Type first"); + alert(wn._("Please select Charge Type first")); d.row_id = ''; } else if((d.charge_type == 'Actual' || d.charge_type == 'On Net Total') && d.row_id) { - alert("You can Enter Row only if your Charge Type is 'On Previous Row Amount' or ' Previous Row Total'"); + alert(wn._("You can Enter Row only if your Charge Type is 'On Previous Row Amount' or ' Previous Row Total'")); d.row_id = ''; } else if((d.charge_type == 'On Previous Row Amount' || d.charge_type == 'On Previous Row Total') && d.row_id){ if(d.row_id >= d.idx){ - alert("You cannot Enter Row no. greater than or equal to current row no. for this Charge type"); + alert(wn._("You cannot Enter Row no. greater than or equal to current row no. for this Charge type")); d.row_id = ''; } } @@ -137,7 +137,7 @@ cur_frm.fields_dict['purchase_tax_details'].grid.get_field("cost_center").get_qu cur_frm.cscript.account_head = function(doc, cdt, cdn) { var d = locals[cdt][cdn]; if(!d.charge_type && d.account_head){ - alert("Please select Charge Type first"); + alert(wn._("Please select Charge Type first")); validated = false; d.account_head = ''; } @@ -151,7 +151,7 @@ cur_frm.cscript.account_head = function(doc, cdt, cdn) { cur_frm.cscript.rate = function(doc, cdt, cdn) { var d = locals[cdt][cdn]; if(!d.charge_type && d.rate) { - alert("Please select Charge Type first"); + alert(wn._("Please select Charge Type first")); d.rate = ''; } validated = false; @@ -161,11 +161,11 @@ cur_frm.cscript.rate = function(doc, cdt, cdn) { cur_frm.cscript.tax_amount = function(doc, cdt, cdn) { var d = locals[cdt][cdn]; if(!d.charge_type && d.tax_amount){ - alert("Please select Charge Type first"); + alert(wn._("Please select Charge Type first")); d.tax_amount = ''; } else if(d.charge_type && d.tax_amount) { - alert("You cannot directly enter Amount and if your Charge Type is Actual enter your amount in Rate"); + alert(wn._("You cannot directly enter Amount and if your Charge Type is Actual enter your amount in Rate")); d.tax_amount = ''; } validated = false; From cc0ef52abd00720d5869b0f70e7a6345cfc0b444 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A1rbara=20Perretti?= Date: Mon, 30 Sep 2013 15:38:40 -0300 Subject: [PATCH 035/200] Fix translate sales_invoice.js --- accounts/doctype/sales_invoice/sales_invoice.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/accounts/doctype/sales_invoice/sales_invoice.js b/accounts/doctype/sales_invoice/sales_invoice.js index aeae28ce03e..b87f6efe4dc 100644 --- a/accounts/doctype/sales_invoice/sales_invoice.js +++ b/accounts/doctype/sales_invoice/sales_invoice.js @@ -60,7 +60,7 @@ erpnext.accounts.SalesInvoiceController = erpnext.selling.SellingController.exte var percent_paid = cint(flt(doc.grand_total - doc.outstanding_amount) / flt(doc.grand_total) * 100); cur_frm.dashboard.add_progress(percent_paid + "% Paid", percent_paid); - cur_frm.add_custom_button('Send SMS', cur_frm.cscript.send_sms); + cur_frm.add_custom_button(wn._('Send SMS'), cur_frm.cscript.send_sms); if(cint(doc.update_stock)!=1) { // show Make Delivery Note button only if Sales Invoice is not created from Delivery Note @@ -71,11 +71,11 @@ erpnext.accounts.SalesInvoiceController = erpnext.selling.SellingController.exte }); if(!from_delivery_note) - cur_frm.add_custom_button('Make Delivery', cur_frm.cscript['Make Delivery Note']); + cur_frm.add_custom_button(wn._('Make Delivery'), cur_frm.cscript['Make Delivery Note']); } if(doc.outstanding_amount!=0) - cur_frm.add_custom_button('Make Payment Entry', cur_frm.cscript.make_bank_voucher); + cur_frm.add_custom_button(wn._('Make Payment Entry'), cur_frm.cscript.make_bank_voucher); } if (doc.docstatus===0) { From dda4e8346998b3abd10a58b8d82e942227677582 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A1rbara=20Perretti?= Date: Mon, 30 Sep 2013 15:43:01 -0300 Subject: [PATCH 036/200] Fix translate sales_taxes_and_charges_master.js --- .../sales_taxes_and_charges_master.js | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/accounts/doctype/sales_taxes_and_charges_master/sales_taxes_and_charges_master.js b/accounts/doctype/sales_taxes_and_charges_master/sales_taxes_and_charges_master.js index f1a602738bf..56e64bc1830 100644 --- a/accounts/doctype/sales_taxes_and_charges_master/sales_taxes_and_charges_master.js +++ b/accounts/doctype/sales_taxes_and_charges_master/sales_taxes_and_charges_master.js @@ -92,7 +92,7 @@ cur_frm.pformat.other_charges= function(doc){ cur_frm.cscript.charge_type = function(doc, cdt, cdn) { var d = locals[cdt][cdn]; if(d.idx == 1 && (d.charge_type == 'On Previous Row Amount' || d.charge_type == 'On Previous Row Total')){ - alert("You cannot select Charge Type as 'On Previous Row Amount' or 'On Previous Row Total' for first row"); + alert(wn._("You cannot select Charge Type as 'On Previous Row Amount' or 'On Previous Row Total' for first row")); d.charge_type = ''; } validated = false; @@ -105,16 +105,16 @@ cur_frm.cscript.charge_type = function(doc, cdt, cdn) { cur_frm.cscript.row_id = function(doc, cdt, cdn) { var d = locals[cdt][cdn]; if(!d.charge_type && d.row_id){ - alert("Please select Charge Type first"); + alert(wn._("Please select Charge Type first")); d.row_id = ''; } else if((d.charge_type == 'Actual' || d.charge_type == 'On Net Total') && d.row_id) { - alert("You can Enter Row only if your Charge Type is 'On Previous Row Amount' or ' Previous Row Total'"); + alert(wn._("You can Enter Row only if your Charge Type is 'On Previous Row Amount' or ' Previous Row Total'")); d.row_id = ''; } else if((d.charge_type == 'On Previous Row Amount' || d.charge_type == 'On Previous Row Total') && d.row_id){ if(d.row_id >= d.idx){ - alert("You cannot Enter Row no. greater than or equal to current row no. for this Charge type"); + alert(wn._("You cannot Enter Row no. greater than or equal to current row no. for this Charge type")); d.row_id = ''; } } @@ -146,7 +146,7 @@ cur_frm.fields_dict['other_charges'].grid.get_field("cost_center").get_query = f cur_frm.cscript.account_head = function(doc, cdt, cdn) { var d = locals[cdt][cdn]; if(!d.charge_type && d.account_head){ - alert("Please select Charge Type first"); + alert(wn._("Please select Charge Type first")); validated = false; d.account_head = ''; } @@ -160,7 +160,7 @@ cur_frm.cscript.account_head = function(doc, cdt, cdn) { cur_frm.cscript.rate = function(doc, cdt, cdn) { var d = locals[cdt][cdn]; if(!d.charge_type && d.rate) { - alert("Please select Charge Type first"); + alert(wn._("Please select Charge Type first")); d.rate = ''; } validated = false; @@ -170,11 +170,11 @@ cur_frm.cscript.rate = function(doc, cdt, cdn) { cur_frm.cscript.tax_amount = function(doc, cdt, cdn) { var d = locals[cdt][cdn]; if(!d.charge_type && d.tax_amount){ - alert("Please select Charge Type first"); + alert(wn._("Please select Charge Type first")); d.tax_amount = ''; } else if(d.charge_type && d.tax_amount) { - alert("You cannot directly enter Amount and if your Charge Type is Actual enter your amount in Rate"); + alert(wn._("You cannot directly enter Amount and if your Charge Type is Actual enter your amount in Rate")); d.tax_amount = ''; } validated = false; From 54edf12900ce306bd7f20f5020834e29f77e9885 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A1rbara=20Perretti?= Date: Mon, 30 Sep 2013 16:38:30 -0300 Subject: [PATCH 037/200] fix translate accounts_browser.js --- .../page/accounts_browser/accounts_browser.js | 88 ++++++++++--------- 1 file changed, 45 insertions(+), 43 deletions(-) diff --git a/accounts/page/accounts_browser/accounts_browser.js b/accounts/page/accounts_browser/accounts_browser.js index 6b577959a13..fafe816cd95 100644 --- a/accounts/page/accounts_browser/accounts_browser.js +++ b/accounts/page/accounts_browser/accounts_browser.js @@ -20,29 +20,31 @@ pscript['onload_Accounts Browser'] = function(wrapper){ chart_area = $("
") .css({"margin-bottom": "15px"}) .appendTo(main), - help_area = $('
\ -

Quick Help

\ -
    \ -
  1. To add child nodes, explore tree and click on the node under which you \ - want to add more nodes.\ -
  2. Accounting Entries can be made against leaf nodes, called Ledgers.\ - Entries against Groups are not allowed.\ -
  3. Please do NOT create Account (Ledgers) for Customers and Suppliers. \ - They are created directly from the Customer / Supplier masters.\ -
  4. To create a Bank Account: Go to the appropriate group \ - (usually Application of Funds > Current Assets > Bank Accounts)\ - and create a new Account Ledger (by clicking on Add Child) of \ - type "Bank or Cash"\ -
  5. To create a Tax Account: Go to the appropriate group \ - (usually Source of Funds > Current Liabilities > Taxes and Duties) \ - and create a new Account Ledger (by clicking on Add Child) of type\ - "Tax" and do mention the Tax rate.\ -
\ -

Please setup your chart of accounts before you start Accounting Entries

\ -
').appendTo(main); + help_area = $('
'+ + '

'+wn._('Quick Help')+'

'+ + '
    '+ + '
  1. '+wn._('To add child nodes, explore tree and click on the node under which you want to add more nodes.')+'
  2. '+ + '
  3. '+ + wn._('Accounting Entries can be made against leaf nodes, called')+ + '' +wn._('Ledgers')+'.'+ wn._('Entries against') + + '' +wn._('Groups') + ''+ wn._('are not allowed.')+ + '
  4. '+ + '
  5. '+wn._('Please do NOT create Account (Ledgers) for Customers and Suppliers. They are created directly from the Customer / Supplier masters.')+'
  6. '+ + '
  7. '+ + ''+wn._('To create a Bank Account:')+''+ + wn._('Go to the appropriate group (usually Application of Funds > Current Assets > Bank Accounts)')+ + wn._('and create a new Account Ledger (by clicking on Add Child) of type "Bank or Cash"')+ + '
  8. '+ + '
  9. '+ + ''+wn._('To create a Tax Account:')+''+ + wn._('Go to the appropriate group (usually Source of Funds > Current Liabilities > Taxes and Duties)')+ + wn._('and create a new Account Ledger (by clicking on Add Child) of type "Tax" and do mention the Tax rate.')+ + '
  10. '+ + '
'+ + '

'+wn._('Please setup your chart of accounts before you start Accounting Entries')+'

').appendTo(main); if (wn.boot.profile.can_create.indexOf("Company") !== -1) { - wrapper.appframe.add_button('New Company', function() { newdoc('Company'); }, + wrapper.appframe.add_button(wn._('New Company'), function() { newdoc('Company'); }, 'icon-plus'); } @@ -145,20 +147,20 @@ erpnext.AccountsChart = Class.extend({ var node_links = []; // edit if (wn.model.can_read(this.ctype) !== -1) { - node_links.push('Edit'); + node_links.push(''+wn._('Edit')+''); } if (data.expandable && wn.boot.profile.in_create.indexOf(this.ctype) !== -1) { - node_links.push('Add Child'); + node_links.push(''+wn._('Add Child')+''); } else if (this.ctype === 'Account' && wn.boot.profile.can_read.indexOf("GL Entry") !== -1) { - node_links.push('View Ledger'); + node_links.push(''+wn._('View Ledger')+''); } if (this.can_write) { - node_links.push('Rename'); + node_links.push(''+wn._('Rename')+''); }; if (this.can_delete) { - node_links.push('Delete'); + node_links.push(''+wn._('Delete')+''); }; link.toolbar.append(node_links.join(" | ")); @@ -204,20 +206,20 @@ erpnext.AccountsChart = Class.extend({ // the dialog var d = new wn.ui.Dialog({ - title:'New Account', + title:wn._('New Account'), fields: [ - {fieldtype:'Data', fieldname:'account_name', label:'New Account Name', reqd:true, - description: "Name of new Account. Note: Please don't create accounts for Customers and Suppliers, \ - they are created automatically from the Customer and Supplier master"}, - {fieldtype:'Select', fieldname:'group_or_ledger', label:'Group or Ledger', - options:'Group\nLedger', description:'Further accounts can be made under Groups,\ - but entries can be made against Ledger'}, - {fieldtype:'Select', fieldname:'account_type', label:'Account Type', + {fieldtype:'Data', fieldname:'account_name', label:wn._('New Account Name'), reqd:true, + description: wn._("Name of new Account. Note: Please don't create accounts for Customers and Suppliers,")+ + wn._("they are created automatically from the Customer and Supplier master")}, + {fieldtype:'Select', fieldname:'group_or_ledger', label:wn._('Group or Ledger'), + options:'Group\nLedger', description: wn._('Further accounts can be made under Groups,')+ + wn._('but entries can be made against Ledger')}, + {fieldtype:'Select', fieldname:'account_type', label:wn._('Account Type'), options: ['', 'Fixed Asset Account', 'Bank or Cash', 'Expense Account', 'Tax', 'Income Account', 'Chargeable'].join('\n'), - description: "Optional. This setting will be used to filter in various transactions." }, - {fieldtype:'Float', fieldname:'tax_rate', label:'Tax Rate'}, - {fieldtype:'Button', fieldname:'create_new', label:'Create New' } + description: wn._("Optional. This setting will be used to filter in various transactions.") }, + {fieldtype:'Float', fieldname:'tax_rate', label:wn._('Tax Rate')}, + {fieldtype:'Button', fieldname:'create_new', label:wn._('Create New') } ] }) @@ -282,13 +284,13 @@ erpnext.AccountsChart = Class.extend({ var me = this; // the dialog var d = new wn.ui.Dialog({ - title:'New Cost Center', + title:wn._('New Cost Center'), fields: [ - {fieldtype:'Data', fieldname:'cost_center_name', label:'New Cost Center Name', reqd:true}, - {fieldtype:'Select', fieldname:'group_or_ledger', label:'Group or Ledger', - options:'Group\nLedger', description:'Further accounts can be made under Groups,\ - but entries can be made against Ledger'}, - {fieldtype:'Button', fieldname:'create_new', label:'Create New' } + {fieldtype:'Data', fieldname:'cost_center_name', label:wn._('New Cost Center Name'), reqd:true}, + {fieldtype:'Select', fieldname:'group_or_ledger', label:wn._('Group or Ledger'), + options:'Group\nLedger', description:wn._('Further accounts can be made under Groups,')+ + wn._('but entries can be made against Ledger')}, + {fieldtype:'Button', fieldname:'create_new', label:wn._('Create New') } ] }); From ad6679f8f123f012b48d446d3de000f26c647d99 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A1rbara=20Perretti?= Date: Mon, 30 Sep 2013 16:42:27 -0300 Subject: [PATCH 038/200] Fix translate accounts_home.js --- accounts/page/accounts_home/accounts_home.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/accounts/page/accounts_home/accounts_home.js b/accounts/page/accounts_home/accounts_home.js index d6c388335f4..daf0206f652 100644 --- a/accounts/page/accounts_home/accounts_home.js +++ b/accounts/page/accounts_home/accounts_home.js @@ -130,7 +130,7 @@ wn.module_page["Accounts"] = [ { "label": wn._("Point-of-Sale Setting"), "doctype":"POS Setting", - "description": "User settings for Point-of-sale (POS)" + "description": wn._("User settings for Point-of-sale (POS)") }, { "doctype":"Budget Distribution", From 9963d5bda35e88ab313c219275a85c8a5f005b93 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A1rbara=20Perretti?= Date: Mon, 30 Sep 2013 16:57:52 -0300 Subject: [PATCH 039/200] Fix translate financial_analytics.js --- .../financial_analytics.js | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/accounts/page/financial_analytics/financial_analytics.js b/accounts/page/financial_analytics/financial_analytics.js index 13b9067760b..7a84dc7aefa 100644 --- a/accounts/page/financial_analytics/financial_analytics.js +++ b/accounts/page/financial_analytics/financial_analytics.js @@ -6,7 +6,7 @@ wn.require("app/js/account_tree_grid.js"); wn.pages['financial-analytics'].onload = function(wrapper) { wn.ui.make_app_page({ parent: wrapper, - title: 'Financial Analytics', + title: wn._('Financial Analytics'), single_column: true }); erpnext.trial_balance = new erpnext.FinancialAnalytics(wrapper, 'Financial Analytics'); @@ -18,7 +18,7 @@ wn.pages['financial-analytics'].onload = function(wrapper) { erpnext.FinancialAnalytics = erpnext.AccountTreeGrid.extend({ filters: [ - {fieldtype:"Select", label: "PL or BS", options:["Profit and Loss", "Balance Sheet"], + {fieldtype:"Select", label: wn._("PL or BS"), options:["Profit and Loss", "Balance Sheet"], filter: function(val, item, opts, me) { if(item._show) return true; @@ -28,19 +28,19 @@ erpnext.FinancialAnalytics = erpnext.AccountTreeGrid.extend({ return me.apply_zero_filter(val, item, opts, me); }}, - {fieldtype:"Select", label: "Company", link:"Company", default_value: "Select Company...", + {fieldtype:"Select", label: wn._("Company"), link:"Company", default_value: "Select Company...", filter: function(val, item, opts) { return item.company == val || val == opts.default_value || item._show; }}, - {fieldtype:"Select", label: "Fiscal Year", link:"Fiscal Year", + {fieldtype:"Select", label: wn._("Fiscal Year"), link:"Fiscal Year", default_value: "Select Fiscal Year..."}, - {fieldtype:"Date", label: "From Date"}, - {fieldtype:"Label", label: "To"}, - {fieldtype:"Date", label: "To Date"}, - {fieldtype:"Select", label: "Range", + {fieldtype:"Date", label: wn._("From Date")}, + {fieldtype:"Label", label: wn._("To")}, + {fieldtype:"Date", label: wn._("To Date")}, + {fieldtype:"Select", label: wn._("Range"), options:["Daily", "Weekly", "Monthly", "Quarterly", "Yearly"]}, - {fieldtype:"Button", label: "Refresh", icon:"icon-refresh icon-white", cssClass:"btn-info"}, - {fieldtype:"Button", label: "Reset Filters"} + {fieldtype:"Button", label: wn._("Refresh"), icon:"icon-refresh icon-white", cssClass:"btn-info"}, + {fieldtype:"Button", label: wn._("Reset Filters")} ], setup_columns: function() { var std_columns = [ From 5d1938775644d977d0bd48dcf1c3f8ee5bbd2ae5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A1rbara=20Perretti?= Date: Mon, 30 Sep 2013 17:07:59 -0300 Subject: [PATCH 040/200] Fix translate financial_statements.js --- accounts/page/financial_statements/financial_statements.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/accounts/page/financial_statements/financial_statements.js b/accounts/page/financial_statements/financial_statements.js index 48931250f2e..20b7bb63e14 100644 --- a/accounts/page/financial_statements/financial_statements.js +++ b/accounts/page/financial_statements/financial_statements.js @@ -6,7 +6,7 @@ erpnext.fs = {} pscript['onload_Financial Statements'] = function(wrapper) { wn.ui.make_app_page({ parent: wrapper, - "title": "Financial Statements", + "title": wn._("Financial Statements"), "single_column": true, }); From 26b13a8a45afa0de3f2aaeb1db5b50fc4b96cc2e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A1rbara=20Perretti?= Date: Mon, 30 Sep 2013 17:26:51 -0300 Subject: [PATCH 041/200] Fix translate general_ledger.js --- .../page/general_ledger/general_ledger.js | 26 +++++++++---------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/accounts/page/general_ledger/general_ledger.js b/accounts/page/general_ledger/general_ledger.js index da28eb3e0a5..23be75d7936 100644 --- a/accounts/page/general_ledger/general_ledger.js +++ b/accounts/page/general_ledger/general_ledger.js @@ -4,7 +4,7 @@ wn.pages['general-ledger'].onload = function(wrapper) { wn.ui.make_app_page({ parent: wrapper, - title: 'General Ledger', + title: wn._('General Ledger'), single_column: true }); @@ -16,7 +16,7 @@ wn.pages['general-ledger'].onload = function(wrapper) { erpnext.GeneralLedger = wn.views.GridReport.extend({ init: function(wrapper) { this._super({ - title: "General Ledger", + title: wn._("General Ledger"), page: wrapper, parent: $(wrapper).find('.layout-main'), appframe: wrapper.appframe, @@ -54,11 +54,11 @@ erpnext.GeneralLedger = wn.views.GridReport.extend({ }, filters: [ - {fieldtype:"Select", label: "Company", link:"Company", default_value: "Select Company...", + {fieldtype:"Select", label: wn._("Company"), link:"Company", default_value: "Select Company...", filter: function(val, item, opts) { return item.company == val || val == opts.default_value; }}, - {fieldtype:"Link", label: "Account", link:"Account", + {fieldtype:"Link", label: wn._("Account"), link:"Account", filter: function(val, item, opts, me) { if(!val) { return true; @@ -68,22 +68,22 @@ erpnext.GeneralLedger = wn.views.GridReport.extend({ return me.is_child_account(val, item.account); } }}, - {fieldtype:"Data", label: "Voucher No", + {fieldtype:"Data", label: wn._("Voucher No"), filter: function(val, item, opts) { if(!val) return true; return (item.voucher_no && item.voucher_no.indexOf(val)!=-1); }}, - {fieldtype:"Date", label: "From Date", filter: function(val, item) { + {fieldtype:"Date", label: wn._("From Date"), filter: function(val, item) { return dateutil.str_to_obj(val) <= dateutil.str_to_obj(item.posting_date); }}, - {fieldtype:"Label", label: "To"}, - {fieldtype:"Date", label: "To Date", filter: function(val, item) { + {fieldtype:"Label", label: wn._("To")}, + {fieldtype:"Date", label: wn._("To Date"), filter: function(val, item) { return dateutil.str_to_obj(val) >= dateutil.str_to_obj(item.posting_date); }}, - {fieldtype: "Check", label: "Group by Ledger"}, - {fieldtype: "Check", label: "Group by Voucher"}, - {fieldtype:"Button", label: "Refresh", icon:"icon-refresh icon-white", cssClass:"btn-info"}, - {fieldtype:"Button", label: "Reset Filters"} + {fieldtype: "Check", label: wn._("Group by Ledger")}, + {fieldtype: "Check", label: wn._("Group by Voucher")}, + {fieldtype:"Button", label: wn._("Refresh"), icon:"icon-refresh icon-white", cssClass:"btn-info"}, + {fieldtype:"Button", label: wn._("Reset Filters")} ], setup_filters: function() { this._super(); @@ -160,7 +160,7 @@ erpnext.GeneralLedger = wn.views.GridReport.extend({ var to_date = dateutil.str_to_obj(this.to_date); if(to_date < from_date) { - msgprint("From Date must be before To Date"); + msgprint(wn._("From Date must be before To Date")); return; } From f2ae1bee20be54c8f64112f41c147068a5da1b6b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A1rbara=20Perretti?= Date: Mon, 30 Sep 2013 17:40:19 -0300 Subject: [PATCH 042/200] Fix translate trial_balance.js --- accounts/page/trial_balance/trial_balance.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/accounts/page/trial_balance/trial_balance.js b/accounts/page/trial_balance/trial_balance.js index 65212562cb8..f4b8736e65e 100644 --- a/accounts/page/trial_balance/trial_balance.js +++ b/accounts/page/trial_balance/trial_balance.js @@ -6,7 +6,7 @@ wn.require("app/js/account_tree_grid.js"); wn.pages['trial-balance'].onload = function(wrapper) { wn.ui.make_app_page({ parent: wrapper, - title: 'Trial Balance', + title: wn._('Trial Balance'), single_column: true }); var TrialBalance = erpnext.AccountTreeGrid.extend({ From e6063695d14a4f5c36f41339db46285593160ac1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A1rbara=20Perretti?= Date: Mon, 30 Sep 2013 17:46:10 -0300 Subject: [PATCH 043/200] Fix translate voucher_import_tool.js --- .../voucher_import_tool.js | 39 +++++++++---------- 1 file changed, 19 insertions(+), 20 deletions(-) diff --git a/accounts/page/voucher_import_tool/voucher_import_tool.js b/accounts/page/voucher_import_tool/voucher_import_tool.js index 5a8538e4dc3..66e7fdcfdc3 100644 --- a/accounts/page/voucher_import_tool/voucher_import_tool.js +++ b/accounts/page/voucher_import_tool/voucher_import_tool.js @@ -4,29 +4,28 @@ wn.pages['voucher-import-tool'].onload = function(wrapper) { wn.ui.make_app_page({ parent: wrapper, - title: 'Voucher Import Tool', + title: wn._('Voucher Import Tool'), single_column: true }); - $(wrapper).find('.layout-main').html('\ -

Import multiple accounting entries via CSV (spreadsheet) file:

\ -

1. Download Template


\ -
\ - \ -

Import multiple vouchers with one debit and one credit entry

\ -
\ -
\ - \ -

Import multiple vouchers with multiple accounts

\ -
\ -
\ -

2. Upload


\ -
\ -

Upload file in CSV format with UTF-8 encoding

\ -
\ -

\ -
\ - '); + $(wrapper).find('.layout-main').html('

'+wn._('Import multiple accounting entries via CSV (spreadsheet) file:')+'

'+ + '

'+wn._('1. Download Template')+'


'+ + '
'+ + ''+ + '

'+wn._('Import multiple vouchers with one debit and one credit entry')+'

'+ + '
'+ + '
'+ + ''+ + '

'+wn._('Import multiple vouchers with multiple accounts')+'

'+ + '
'+ + '
'+ + '

'+wn._('2. Upload')+'


'+ + '
'+ + '

'+wn._('Upload file in CSV format with UTF-8 encoding')+'

'+ + '
'+ + '

'+ + '
'+ + ''); wn.upload.make({ parent: $(wrapper).find("#voucher-upload"), From af9f4ed7fb171c36550cf1b89f4d1efb65045f1a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A1rbara=20Perretti?= Date: Mon, 30 Sep 2013 17:48:51 -0300 Subject: [PATCH 044/200] Fix translate sales_person_target_variance_item_group_wise.js --- .../sales_person_target_variance_item_group_wise.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/selling/report/sales_person_target_variance_item_group_wise/sales_person_target_variance_item_group_wise.js b/selling/report/sales_person_target_variance_item_group_wise/sales_person_target_variance_item_group_wise.js index 5f2b89cbbd8..d41adb6ddee 100644 --- a/selling/report/sales_person_target_variance_item_group_wise/sales_person_target_variance_item_group_wise.js +++ b/selling/report/sales_person_target_variance_item_group_wise/sales_person_target_variance_item_group_wise.js @@ -5,21 +5,21 @@ wn.query_reports["Sales Person Target Variance Item Group-Wise"] = { "filters": [ { fieldname: "fiscal_year", - label: "Fiscal Year", + label: wn._("Fiscal Year"), fieldtype: "Link", options: "Fiscal Year", default: sys_defaults.fiscal_year }, { fieldname: "period", - label: "Period", + label: wn._("Period"), fieldtype: "Select", options: "Monthly\nQuarterly\nHalf-Yearly\nYearly", default: "Monthly" }, { fieldname: "target_on", - label: "Target On", + label: wn._("Target On"), fieldtype: "Select", options: "Quantity\nAmount", default: "Quantity" From 633e3729f4f09cf8450ceb746b333b12c41a55e9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A1rbara=20Perretti?= Date: Mon, 30 Sep 2013 17:51:14 -0300 Subject: [PATCH 045/200] fix translate sales_person_wise_transaction_summary.js --- .../sales_person_wise_transaction_summary.js | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/selling/report/sales_person_wise_transaction_summary/sales_person_wise_transaction_summary.js b/selling/report/sales_person_wise_transaction_summary/sales_person_wise_transaction_summary.js index 6ddb5f97c9d..1f62084f473 100644 --- a/selling/report/sales_person_wise_transaction_summary/sales_person_wise_transaction_summary.js +++ b/selling/report/sales_person_wise_transaction_summary/sales_person_wise_transaction_summary.js @@ -5,57 +5,57 @@ wn.query_reports["Sales Person-wise Transaction Summary"] = { "filters": [ { fieldname: "sales_person", - label: "Sales Person", + label: wn._("Sales Person"), fieldtype: "Link", options: "Sales Person" }, { fieldname: "doc_type", - label: "Document Type", + label: wn._("Document Type"), fieldtype: "Select", options: "Sales Order\nDelivery Note\nSales Invoice", default: "Sales Order" }, { fieldname: "from_date", - label: "From Date", + label: wn._("From Date"), fieldtype: "Date", default: wn.defaults.get_user_default("year_start_date"), }, { fieldname:"to_date", - label: "To Date", + label: wn._("To Date"), fieldtype: "Date", default: get_today() }, { fieldname:"company", - label: "Company", + label: wn._("Company"), fieldtype: "Link", options: "Company", default: wn.defaults.get_default("company") }, { fieldname:"item_group", - label: "Item Group", + label: wn._("Item Group"), fieldtype: "Link", options: "Item Group", }, { fieldname:"brand", - label: "Brand", + label: wn._("Brand"), fieldtype: "Link", options: "Brand", }, { fieldname:"customer", - label: "Customer", + label: wn._("Customer"), fieldtype: "Link", options: "Customer", }, { fieldname:"territory", - label: "Territory", + label: wn._("Territory"), fieldtype: "Link", options: "Territory", }, From 7339ca50f4b2bb145bd93700813d8177334677d9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A1rbara=20Perretti?= Date: Mon, 30 Sep 2013 17:53:05 -0300 Subject: [PATCH 046/200] Fix translate territory_target_variance_item_group_wise.js --- .../territory_target_variance_item_group_wise.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/selling/report/territory_target_variance_item_group_wise/territory_target_variance_item_group_wise.js b/selling/report/territory_target_variance_item_group_wise/territory_target_variance_item_group_wise.js index 882cdb6e83a..ce2bc9f16c2 100644 --- a/selling/report/territory_target_variance_item_group_wise/territory_target_variance_item_group_wise.js +++ b/selling/report/territory_target_variance_item_group_wise/territory_target_variance_item_group_wise.js @@ -5,21 +5,21 @@ wn.query_reports["Territory Target Variance Item Group-Wise"] = { "filters": [ { fieldname: "fiscal_year", - label: "Fiscal Year", + label: wn._("Fiscal Year"), fieldtype: "Link", options: "Fiscal Year", default: sys_defaults.fiscal_year }, { fieldname: "period", - label: "Period", + label: wn._("Period"), fieldtype: "Select", options: "Monthly\nQuarterly\nHalf-Yearly\nYearly", default: "Monthly" }, { fieldname: "target_on", - label: "Target On", + label: wn._("Target On"), fieldtype: "Select", options: "Quantity\nAmount", default: "Quantity" From 8bb82aeac31acd601f8d0c17b97b873e729e7857 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A1rbara=20Perretti?= Date: Mon, 30 Sep 2013 17:57:17 -0300 Subject: [PATCH 047/200] Fix translate accounts_payable.js --- accounts/report/accounts_payable/accounts_payable.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/accounts/report/accounts_payable/accounts_payable.js b/accounts/report/accounts_payable/accounts_payable.js index 2c6c918e57e..86516fc5505 100644 --- a/accounts/report/accounts_payable/accounts_payable.js +++ b/accounts/report/accounts_payable/accounts_payable.js @@ -5,14 +5,14 @@ wn.query_reports["Accounts Payable"] = { "filters": [ { "fieldname":"company", - "label": "Company", + "label": wn._("Company"), "fieldtype": "Link", "options": "Company", "default": wn.defaults.get_default("company") }, { "fieldname":"account", - "label": "Account", + "label": wn._("Account"), "fieldtype": "Link", "options": "Account", "get_query": function() { @@ -30,13 +30,13 @@ wn.query_reports["Accounts Payable"] = { }, { "fieldname":"report_date", - "label": "Date", + "label": wn._("Date"), "fieldtype": "Date", "default": get_today() }, { "fieldname":"ageing_based_on", - "label": "Ageing Based On", + "label": wn._("Ageing Based On"), "fieldtype": "Select", "options": 'Posting Date' + NEWLINE + 'Due Date', "default": "Posting Date" From 4a7b199c4de9ffa6688f3d43b6d0c7c98c704460 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A1rbara=20Perretti?= Date: Mon, 30 Sep 2013 18:06:29 -0300 Subject: [PATCH 048/200] Fix translate accounts_receivable.js --- .../report/accounts_receivable/accounts_receivable.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/accounts/report/accounts_receivable/accounts_receivable.js b/accounts/report/accounts_receivable/accounts_receivable.js index 5f0b1901c31..65588a661bc 100644 --- a/accounts/report/accounts_receivable/accounts_receivable.js +++ b/accounts/report/accounts_receivable/accounts_receivable.js @@ -5,14 +5,14 @@ wn.query_reports["Accounts Receivable"] = { "filters": [ { "fieldname":"company", - "label": "Company", + "label": wn._("Company"), "fieldtype": "Link", "options": "Company", "default": wn.defaults.get_default("company") }, { "fieldname":"account", - "label": "Account", + "label": wn._("Account"), "fieldtype": "Link", "options": "Account", "get_query": function() { @@ -30,13 +30,13 @@ wn.query_reports["Accounts Receivable"] = { }, { "fieldname":"report_date", - "label": "Date", + "label": wn._("Date"), "fieldtype": "Date", "default": get_today() }, { "fieldname":"ageing_based_on", - "label": "Ageing Based On", + "label": wn._("Ageing Based On"), "fieldtype": "Select", "options": 'Posting Date' + NEWLINE + 'Due Date', "default": "Posting Date" From 0a857b21d39b75b6a56dabd03430298f2d5301fb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A1rbara=20Perretti?= Date: Mon, 30 Sep 2013 18:07:42 -0300 Subject: [PATCH 049/200] Fix translate bank_clearance_summary.js --- .../report/bank_clearance_summary/bank_clearance_summary.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/accounts/report/bank_clearance_summary/bank_clearance_summary.js b/accounts/report/bank_clearance_summary/bank_clearance_summary.js index 8e6d0c04fe4..fbc973a052b 100644 --- a/accounts/report/bank_clearance_summary/bank_clearance_summary.js +++ b/accounts/report/bank_clearance_summary/bank_clearance_summary.js @@ -5,20 +5,20 @@ wn.query_reports["Bank Clearance Summary"] = { "filters": [ { "fieldname":"from_date", - "label": "From Date", + "label": wn._("From Date"), "fieldtype": "Date", "default": wn.defaults.get_user_default("year_start_date"), "width": "80" }, { "fieldname":"to_date", - "label": "To Date", + "label": wn._("To Date"), "fieldtype": "Date", "default": get_today() }, { "fieldname":"account", - "label": "Bank Account", + "label": wn._("Bank Account"), "fieldtype": "Link", "options": "Account", "get_query": function() { From 2d393e36a5d4dab5e338f1fddfd090d0e5316b9b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A1rbara=20Perretti?= Date: Mon, 30 Sep 2013 18:08:50 -0300 Subject: [PATCH 050/200] Fix translate bank_reconciliation_statement.js --- .../bank_reconciliation_statement.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/accounts/report/bank_reconciliation_statement/bank_reconciliation_statement.js b/accounts/report/bank_reconciliation_statement/bank_reconciliation_statement.js index bf971a7f972..420e0870189 100644 --- a/accounts/report/bank_reconciliation_statement/bank_reconciliation_statement.js +++ b/accounts/report/bank_reconciliation_statement/bank_reconciliation_statement.js @@ -5,7 +5,7 @@ wn.query_reports["Bank Reconciliation Statement"] = { "filters": [ { "fieldname":"account", - "label": "Bank Account", + "label": wn._("Bank Account"), "fieldtype": "Link", "options": "Account", "get_query": function() { @@ -20,7 +20,7 @@ wn.query_reports["Bank Reconciliation Statement"] = { }, { "fieldname":"report_date", - "label": "Date", + "label": wn._("Date"), "fieldtype": "Date", "default": get_today() }, From 2d3041e8ae7a061bf20bc501c5b2edcd9b9d5acf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A1rbara=20Perretti?= Date: Mon, 30 Sep 2013 18:10:04 -0300 Subject: [PATCH 051/200] Fix translate budget_variance_report.js --- .../report/budget_variance_report/budget_variance_report.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/accounts/report/budget_variance_report/budget_variance_report.js b/accounts/report/budget_variance_report/budget_variance_report.js index 2ed60182681..908963fe14f 100644 --- a/accounts/report/budget_variance_report/budget_variance_report.js +++ b/accounts/report/budget_variance_report/budget_variance_report.js @@ -5,21 +5,21 @@ wn.query_reports["Budget Variance Report"] = { "filters": [ { fieldname: "fiscal_year", - label: "Fiscal Year", + label: wn._("Fiscal Year"), fieldtype: "Link", options: "Fiscal Year", default: sys_defaults.fiscal_year }, { fieldname: "period", - label: "Period", + label: wn._("Period"), fieldtype: "Select", options: "Monthly\nQuarterly\nHalf-Yearly\nYearly", default: "Monthly" }, { fieldname: "company", - label: "Company", + label: wn._("Company"), fieldtype: "Link", options: "Company", default: wn.defaults.get_default("company") From c685da006126656b82d52e237818a3dd69c97dc8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A1rbara=20Perretti?= Date: Mon, 30 Sep 2013 18:11:48 -0300 Subject: [PATCH 052/200] Fix translate gross_profit.js --- accounts/report/gross_profit/gross_profit.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/accounts/report/gross_profit/gross_profit.js b/accounts/report/gross_profit/gross_profit.js index aea0b8a4e40..ee95f72974e 100644 --- a/accounts/report/gross_profit/gross_profit.js +++ b/accounts/report/gross_profit/gross_profit.js @@ -5,20 +5,20 @@ wn.query_reports["Gross Profit"] = { "filters": [ { "fieldname":"company", - "label": "Company", + "label": wn._("Company"), "fieldtype": "Link", "options": "Company", "default": wn.defaults.get_user_default("company") }, { "fieldname":"from_date", - "label": "From Date", + "label": wn._("From Date"), "fieldtype": "Date", "default": wn.defaults.get_user_default("year_start_date") }, { "fieldname":"to_date", - "label": "To Date", + "label": wn._("To Date"), "fieldtype": "Date", "default": wn.defaults.get_user_default("year_end_date") }, From 40c98fb795f95ba8d2fd5e27cfa5918a6ac7baf1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A1rbara=20Perretti?= Date: Mon, 30 Sep 2013 18:13:24 -0300 Subject: [PATCH 053/200] Fix translate item_wise_purchase_register.js --- .../item_wise_purchase_register.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/accounts/report/item_wise_purchase_register/item_wise_purchase_register.js b/accounts/report/item_wise_purchase_register/item_wise_purchase_register.js index 457c9a80009..19970b7df12 100644 --- a/accounts/report/item_wise_purchase_register/item_wise_purchase_register.js +++ b/accounts/report/item_wise_purchase_register/item_wise_purchase_register.js @@ -5,26 +5,26 @@ wn.query_reports["Item-wise Purchase Register"] = { "filters": [ { "fieldname":"from_date", - "label": "From Date", + "label": wn._("From Date"), "fieldtype": "Date", "default": wn.defaults.get_user_default("year_start_date"), "width": "80" }, { "fieldname":"to_date", - "label": "To Date", + "label": wn._("To Date"), "fieldtype": "Date", "default": get_today() }, { "fieldname": "item_code", - "label": "Item", + "label": wn._("Item"), "fieldtype": "Link", "options": "Item", }, { "fieldname":"account", - "label": "Account", + "label": wn._("Account"), "fieldtype": "Link", "options": "Account", "get_query": function() { @@ -42,7 +42,7 @@ wn.query_reports["Item-wise Purchase Register"] = { }, { "fieldname":"company", - "label": "Company", + "label": wn._("Company"), "fieldtype": "Link", "options": "Company", "default": wn.defaults.get_default("company") From aa83cd03948d41d191421d6297700fe84d6f76b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A1rbara=20Perretti?= Date: Mon, 30 Sep 2013 18:14:43 -0300 Subject: [PATCH 054/200] Fix translate item_wise_sales_register.js --- .../item_wise_sales_register/item_wise_sales_register.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/accounts/report/item_wise_sales_register/item_wise_sales_register.js b/accounts/report/item_wise_sales_register/item_wise_sales_register.js index c131fbde64f..068c33dc6eb 100644 --- a/accounts/report/item_wise_sales_register/item_wise_sales_register.js +++ b/accounts/report/item_wise_sales_register/item_wise_sales_register.js @@ -5,20 +5,20 @@ wn.query_reports["Item-wise Sales Register"] = wn.query_reports["Sales Register" "filters": [ { "fieldname":"from_date", - "label": "From Date", + "label": wn._("From Date"), "fieldtype": "Date", "default": wn.defaults.get_default("year_start_date"), "width": "80" }, { "fieldname":"to_date", - "label": "To Date", + "label": wn._("To Date"), "fieldtype": "Date", "default": get_today() }, { "fieldname":"account", - "label": "Account", + "label": wn._("Account"), "fieldtype": "Link", "options": "Account", "get_query": function() { @@ -36,7 +36,7 @@ wn.query_reports["Item-wise Sales Register"] = wn.query_reports["Sales Register" }, { "fieldname":"company", - "label": "Company", + "label": wn._("Company"), "fieldtype": "Link", "options": "Company", "default": wn.defaults.get_default("company") From e696cd0b6c1735d25265dda44ca9a43b349f8a36 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A1rbara=20Perretti?= Date: Mon, 30 Sep 2013 18:17:35 -0300 Subject: [PATCH 055/200] Fix translate payment_collection_with_ageing.js --- .../payment_collection_with_ageing.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/accounts/report/payment_collection_with_ageing/payment_collection_with_ageing.js b/accounts/report/payment_collection_with_ageing/payment_collection_with_ageing.js index 8d8c7464676..e619a43d0fe 100644 --- a/accounts/report/payment_collection_with_ageing/payment_collection_with_ageing.js +++ b/accounts/report/payment_collection_with_ageing/payment_collection_with_ageing.js @@ -5,20 +5,20 @@ wn.query_reports["Payment Collection With Ageing"] = { "filters": [ { "fieldname": "from_date", - "label": "From Date", + "label": wn._("From Date"), "fieldtype": "Date", "default": wn.defaults.get_user_default("year_start_date"), "width": "80" }, { "fieldname":"to_date", - "label": "To Date", + "label": wn._("To Date"), "fieldtype": "Date", "default": get_today() }, { "fieldname":"account", - "label": "Customer Account", + "label": wn._("Customer Account"), "fieldtype": "Link", "options": "Account", "get_query": function() { @@ -36,7 +36,7 @@ wn.query_reports["Payment Collection With Ageing"] = { }, { "fieldname":"company", - "label": "Company", + "label": wn._("Company"), "fieldtype": "Link", "options": "Company", "default": wn.defaults.get_default("company") From 2fec756fdeb12353daec169e41afcb3db0ea675a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A1rbara=20Perretti?= Date: Mon, 30 Sep 2013 18:19:03 -0300 Subject: [PATCH 056/200] Fix translate payment_made_with_ageing.js --- .../payment_made_with_ageing/payment_made_with_ageing.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/accounts/report/payment_made_with_ageing/payment_made_with_ageing.js b/accounts/report/payment_made_with_ageing/payment_made_with_ageing.js index 7b80bdeaed4..101df80a8cd 100644 --- a/accounts/report/payment_made_with_ageing/payment_made_with_ageing.js +++ b/accounts/report/payment_made_with_ageing/payment_made_with_ageing.js @@ -5,19 +5,19 @@ wn.query_reports["Payment Made With Ageing"] = { "filters": [ { fieldname: "from_date", - label: "From Date", + label: wn._("From Date"), fieldtype: "Date", default: wn.defaults.get_user_default("year_start_date"), }, { fieldname:"to_date", - label: "To Date", + label: wn._("To Date"), fieldtype: "Date", default: get_today() }, { fieldname:"account", - label: "Supplier Account", + label: wn._("Supplier Account"), fieldtype: "Link", options: "Account", get_query: function() { @@ -34,7 +34,7 @@ wn.query_reports["Payment Made With Ageing"] = { }, { fieldname:"company", - label: "Company", + label: wn._("Company"), fieldtype: "Link", options: "Company", default: wn.defaults.get_default("company") From 35fe5faba532bffed0f7b9a6a60ed21807f1f83c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A1rbara=20Perretti?= Date: Mon, 30 Sep 2013 18:19:58 -0300 Subject: [PATCH 057/200] Fix translate purchase_register.js --- accounts/report/purchase_register/purchase_register.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/accounts/report/purchase_register/purchase_register.js b/accounts/report/purchase_register/purchase_register.js index 5944b1a0592..0bd713fd08c 100644 --- a/accounts/report/purchase_register/purchase_register.js +++ b/accounts/report/purchase_register/purchase_register.js @@ -5,20 +5,20 @@ wn.query_reports["Purchase Register"] = { "filters": [ { "fieldname":"from_date", - "label": "From Date", + "label": wn._("From Date"), "fieldtype": "Date", "default": wn.defaults.get_user_default("year_start_date"), "width": "80" }, { "fieldname":"to_date", - "label": "To Date", + "label": wn._("To Date"), "fieldtype": "Date", "default": get_today() }, { "fieldname":"account", - "label": "Account", + "label": wn._("Account"), "fieldtype": "Link", "options": "Account", "get_query": function() { @@ -36,7 +36,7 @@ wn.query_reports["Purchase Register"] = { }, { "fieldname":"company", - "label": "Company", + "label": wn._("Company"), "fieldtype": "Link", "options": "Company", "default": wn.defaults.get_default("company") From 48dbeb63b8def4fde9dc4cce8c212dc1fcc146ea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A1rbara=20Perretti?= Date: Mon, 30 Sep 2013 18:21:02 -0300 Subject: [PATCH 058/200] Fix translate sales_register.js --- accounts/report/sales_register/sales_register.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/accounts/report/sales_register/sales_register.js b/accounts/report/sales_register/sales_register.js index 43c841f1325..ab3fcd7a35c 100644 --- a/accounts/report/sales_register/sales_register.js +++ b/accounts/report/sales_register/sales_register.js @@ -5,20 +5,20 @@ wn.query_reports["Sales Register"] = { "filters": [ { "fieldname":"from_date", - "label": "From Date", + "label": wn._("From Date"), "fieldtype": "Date", "default": wn.defaults.get_default("year_start_date"), "width": "80" }, { "fieldname":"to_date", - "label": "To Date", + "label": wn._("To Date"), "fieldtype": "Date", "default": get_today() }, { "fieldname":"account", - "label": "Account", + "label": wn._("Account"), "fieldtype": "Link", "options": "Account", "get_query": function() { @@ -36,7 +36,7 @@ wn.query_reports["Sales Register"] = { }, { "fieldname":"company", - "label": "Company", + "label": wn._("Company"), "fieldtype": "Link", "options": "Company", "default": wn.defaults.get_default("company") From e37cc01d16c5682c2c3e844fb5b444c36016d405 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A1rbara=20Perretti?= Date: Mon, 30 Sep 2013 18:39:43 -0300 Subject: [PATCH 059/200] Fix translate voucher_import_tool.js --- accounts/page/voucher_import_tool/voucher_import_tool.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/accounts/page/voucher_import_tool/voucher_import_tool.js b/accounts/page/voucher_import_tool/voucher_import_tool.js index 66e7fdcfdc3..854617b227e 100644 --- a/accounts/page/voucher_import_tool/voucher_import_tool.js +++ b/accounts/page/voucher_import_tool/voucher_import_tool.js @@ -9,7 +9,7 @@ wn.pages['voucher-import-tool'].onload = function(wrapper) { }); $(wrapper).find('.layout-main').html('

'+wn._('Import multiple accounting entries via CSV (spreadsheet) file:')+'

'+ - '

'+wn._('1. Download Template')+'


'+ + '

1.'+wn._(' Download Template')+'


'+ '
'+ ''+ '

'+wn._('Import multiple vouchers with one debit and one credit entry')+'

'+ @@ -19,7 +19,7 @@ wn.pages['voucher-import-tool'].onload = function(wrapper) { '

'+wn._('Import multiple vouchers with multiple accounts')+'

'+ '
'+ '
'+ - '

'+wn._('2. Upload')+'


'+ + '

2.'+wn._(' Upload')+'


'+ '
'+ '

'+wn._('Upload file in CSV format with UTF-8 encoding')+'

'+ '
'+ From c52cbef184e646825cd4340141d9203b209969b4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A1rbara=20Perretti?= Date: Mon, 30 Sep 2013 19:02:50 -0300 Subject: [PATCH 060/200] Fix translate general_ledger.js --- .../page/general_ledger/general_ledger.js | 21 ++++++++++--------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/accounts/page/general_ledger/general_ledger.js b/accounts/page/general_ledger/general_ledger.js index 23be75d7936..25cf8406454 100644 --- a/accounts/page/general_ledger/general_ledger.js +++ b/accounts/page/general_ledger/general_ledger.js @@ -24,39 +24,40 @@ erpnext.GeneralLedger = wn.views.GridReport.extend({ }); }, setup_columns: function() { + var DEFAULT_COMPANY_VALUE = wn._("Select Company..."); this.columns = [ - {id: "posting_date", name: "Posting Date", field: "posting_date", width: 100, + {id: "posting_date", name: wn._("Posting Date"), field: "posting_date", width: 100, formatter: this.date_formatter}, - {id: "account", name: "Account", field: "account", width: 240, + {id: "account", name: wn._("Account"), field: "account", width: 240, link_formatter: { filter_input: "account", open_btn: true, doctype: "'Account'" }}, - {id: "against_account", name: "Against Account", field: "against_account", + {id: "against_account", name: wn._("Against Account"), field: "against_account", width: 240, hidden: !this.account}, - {id: "debit", name: "Debit", field: "debit", width: 100, + {id: "debit", name: wn._("Debit"), field: "debit", width: 100, formatter: this.currency_formatter}, - {id: "credit", name: "Credit", field: "credit", width: 100, + {id: "credit", name: wn._("Credit"), field: "credit", width: 100, formatter: this.currency_formatter}, - {id: "voucher_type", name: "Voucher Type", field: "voucher_type", width: 120}, - {id: "voucher_no", name: "Voucher No", field: "voucher_no", width: 160, + {id: "voucher_type", name: wn._("Voucher Type"), field: "voucher_type", width: 120}, + {id: "voucher_no", name: wn._("Voucher No"), field: "voucher_no", width: 160, link_formatter: { filter_input: "voucher_no", open_btn: true, doctype: "dataContext.voucher_type" }}, - {id: "remarks", name: "Remarks", field: "remarks", width: 200, + {id: "remarks", name: wn._("Remarks"), field: "remarks", width: 200, formatter: this.text_formatter}, ]; }, filters: [ - {fieldtype:"Select", label: wn._("Company"), link:"Company", default_value: "Select Company...", + {fieldtype:"Select", label: wn._("Company"), link:"Company", default_value: DEFAULT_COMPANY_VALUE, filter: function(val, item, opts) { - return item.company == val || val == opts.default_value; + return item.company == val || val == DEFAULT_COMPANY_VALUE; }}, {fieldtype:"Link", label: wn._("Account"), link:"Account", filter: function(val, item, opts, me) { From e99c5581527707728cb0af412e26b9dd2a052e96 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A1rbara=20Perretti?= Date: Mon, 30 Sep 2013 19:04:16 -0300 Subject: [PATCH 061/200] Fix trasnlate trial_balance.js --- accounts/page/trial_balance/trial_balance.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/accounts/page/trial_balance/trial_balance.js b/accounts/page/trial_balance/trial_balance.js index f4b8736e65e..ec14c51e884 100644 --- a/accounts/page/trial_balance/trial_balance.js +++ b/accounts/page/trial_balance/trial_balance.js @@ -17,8 +17,8 @@ wn.pages['trial-balance'].onload = function(wrapper) { // period closing entry checkbox this.wrapper.bind("make", function() { $('
\ - With period closing entry
') + class="with_period_closing_entry">' + + wn._("With period closing entry") + '
') .appendTo(me.wrapper) .find("input").click(function() { me.refresh(); }); }); From d4279c7fe50d9fd211b7834f8100f42d26813efa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A1rbara=20Perretti?= Date: Mon, 30 Sep 2013 19:05:32 -0300 Subject: [PATCH 062/200] Fix translate voucher_import_tool.js --- .../voucher_import_tool.js | 28 +++++++++++-------- 1 file changed, 17 insertions(+), 11 deletions(-) diff --git a/accounts/page/voucher_import_tool/voucher_import_tool.js b/accounts/page/voucher_import_tool/voucher_import_tool.js index 854617b227e..67d4aec1392 100644 --- a/accounts/page/voucher_import_tool/voucher_import_tool.js +++ b/accounts/page/voucher_import_tool/voucher_import_tool.js @@ -8,21 +8,27 @@ wn.pages['voucher-import-tool'].onload = function(wrapper) { single_column: true }); - $(wrapper).find('.layout-main').html('

'+wn._('Import multiple accounting entries via CSV (spreadsheet) file:')+'

'+ - '

1.'+wn._(' Download Template')+'


'+ + $(wrapper).find('.layout-main').html('

' + + wn._('Import multiple accounting entries via CSV (spreadsheet) file:') + + '

1. ' + wn._('Download Template') + '


' + + '
' + + '' + + '

' + + wn._('Import multiple vouchers with one debit and one credit entry') + + '

'+ '
'+ - ''+ - '

'+wn._('Import multiple vouchers with one debit and one credit entry')+'

'+ - '
'+ - '
'+ - ''+ - '

'+wn._('Import multiple vouchers with multiple accounts')+'

'+ + '

' + + wn._('Import multiple vouchers with multiple accounts')+ + '

'+ '
'+ '
'+ - '

2.'+wn._(' Upload')+'


'+ + '

2. ' + wn._('Upload') + '


'+ '
'+ - '

'+wn._('Upload file in CSV format with UTF-8 encoding')+'

'+ - '
'+ + '

' + wn._('Upload file in CSV format with UTF-8 encoding') + + '

'+ '

'+ '
'+ ''); From 9b4a23312630b2da59b1cbd93e9d14ec5ba14782 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A1rbara=20Perretti?= Date: Tue, 1 Oct 2013 15:23:50 -0300 Subject: [PATCH 063/200] Fix translate financial_statements.js --- accounts/page/financial_statements/financial_statements.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/accounts/page/financial_statements/financial_statements.js b/accounts/page/financial_statements/financial_statements.js index 20b7bb63e14..6ea2c7d3297 100644 --- a/accounts/page/financial_statements/financial_statements.js +++ b/accounts/page/financial_statements/financial_statements.js @@ -45,7 +45,7 @@ pscript['onload_Financial Statements'] = function(wrapper) { $(wrapper).find(".layout-main").html('').css({"min-height": "400px"}); // load companies @@ -61,7 +61,7 @@ pscript['onload_Financial Statements'] = function(wrapper) { pscript.stmt_new = function(stmt,company_name,level,period,year) { - $i('stmt_tree').innerHTML = 'Refreshing....'; + $i('stmt_tree').innerHTML = wn._('Refreshing....'); $i('stmt_tree').style.display = 'block'; var company =erpnext.fs.stmt_company.get_value(); From 4235fa03bc27cffeb9a1af8755a401dd6efa4837 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A1rbara=20Perretti?= Date: Tue, 1 Oct 2013 16:25:11 -0300 Subject: [PATCH 064/200] fix translate purchase_order.js --- buying/doctype/purchase_order/purchase_order.js | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/buying/doctype/purchase_order/purchase_order.js b/buying/doctype/purchase_order/purchase_order.js index a960046b75c..fb452033c73 100644 --- a/buying/doctype/purchase_order/purchase_order.js +++ b/buying/doctype/purchase_order/purchase_order.js @@ -23,19 +23,19 @@ erpnext.buying.PurchaseOrderController = erpnext.buying.BuyingController.extend( doc.per_billed); - cur_frm.add_custom_button('Send SMS', cur_frm.cscript['Send SMS']); + cur_frm.add_custom_button(wn._('Send SMS'), cur_frm.cscript['Send SMS']); if(flt(doc.per_received, 2) < 100) - cur_frm.add_custom_button('Make Purchase Receipt', this.make_purchase_receipt); + cur_frm.add_custom_button(wn._('Make Purchase Receipt'), this.make_purchase_receipt); if(flt(doc.per_billed, 2) < 100) - cur_frm.add_custom_button('Make Invoice', this.make_purchase_invoice); + cur_frm.add_custom_button(wn._('Make Invoice'), this.make_purchase_invoice); if(flt(doc.per_billed, 2) < 100 || doc.per_received < 100) - cur_frm.add_custom_button('Stop', cur_frm.cscript['Stop Purchase Order']); + cur_frm.add_custom_button(wn._('Stop'), cur_frm.cscript['Stop Purchase Order']); } else if(doc.docstatus===0) { cur_frm.cscript.add_from_mappers(); } if(doc.docstatus == 1 && doc.status == 'Stopped') - cur_frm.add_custom_button('Unstop Purchase Order', + cur_frm.add_custom_button(wn._('Unstop Purchase Order'), cur_frm.cscript['Unstop Purchase Order']); }, @@ -136,7 +136,7 @@ cur_frm.cscript.get_last_purchase_rate = function(doc, cdt, cdn){ cur_frm.cscript['Stop Purchase Order'] = function() { var doc = cur_frm.doc; - var check = confirm("Do you really want to STOP " + doc.name); + var check = confirm(wn._("Do you really want to STOP ") + doc.name); if (check) { return $c('runserverobj', args={'method':'update_status', 'arg': 'Stopped', 'docs': wn.model.compress(make_doclist(doc.doctype, doc.name))}, function(r,rt) { @@ -147,7 +147,7 @@ cur_frm.cscript['Stop Purchase Order'] = function() { cur_frm.cscript['Unstop Purchase Order'] = function() { var doc = cur_frm.doc; - var check = confirm("Do you really want to UNSTOP " + doc.name); + var check = confirm(wn._("Do you really want to UNSTOP ") + doc.name); if (check) { return $c('runserverobj', args={'method':'update_status', 'arg': 'Submitted', 'docs': wn.model.compress(make_doclist(doc.doctype, doc.name))}, function(r,rt) { From 7d11909dde080deb7444a91f132ebee84cba2a7a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A1rbara=20Perretti?= Date: Tue, 1 Oct 2013 16:38:00 -0300 Subject: [PATCH 065/200] Fix translate supplier.js --- buying/doctype/supplier/supplier.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/buying/doctype/supplier/supplier.js b/buying/doctype/supplier/supplier.js index 75542c82579..a4c6de02771 100644 --- a/buying/doctype/supplier/supplier.js +++ b/buying/doctype/supplier/supplier.js @@ -71,7 +71,7 @@ cur_frm.cscript.make_address = function() { return "select name, address_type, address_line1, address_line2, city, state, country, pincode, fax, email_id, phone, is_primary_address, is_shipping_address from tabAddress where supplier='"+cur_frm.docname+"' and docstatus != 2 order by is_primary_address desc" }, as_dict: 1, - no_results_message: 'No addresses created', + no_results_message: wn._('No addresses created'), render_row: cur_frm.cscript.render_address_row, }); // note: render_address_row is defined in contact_control.js @@ -89,7 +89,7 @@ cur_frm.cscript.make_contact = function() { return "select name, first_name, last_name, email_id, phone, mobile_no, department, designation, is_primary_contact from tabContact where supplier='"+cur_frm.docname+"' and docstatus != 2 order by is_primary_contact desc" }, as_dict: 1, - no_results_message: 'No contacts created', + no_results_message: wn._('No contacts created'), render_row: cur_frm.cscript.render_contact_row, }); // note: render_contact_row is defined in contact_control.js From e17417af43533c537865248ec6cb57eb811bd891 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A1rbara=20Perretti?= Date: Tue, 1 Oct 2013 19:14:55 -0300 Subject: [PATCH 066/200] Fix translate delivery_note.js --- stock/doctype/delivery_note/delivery_note.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/stock/doctype/delivery_note/delivery_note.js b/stock/doctype/delivery_note/delivery_note.js index 40d840011a9..1542c7aa118 100644 --- a/stock/doctype/delivery_note/delivery_note.js +++ b/stock/doctype/delivery_note/delivery_note.js @@ -25,20 +25,20 @@ erpnext.stock.DeliveryNoteController = erpnext.selling.SellingController.extend( }); if(!from_sales_invoice) - cur_frm.add_custom_button('Make Invoice', this.make_sales_invoice); + cur_frm.add_custom_button(wn._('Make Invoice'), this.make_sales_invoice); } if(flt(doc.per_installed, 2) < 100 && doc.docstatus==1) - cur_frm.add_custom_button('Make Installation Note', this.make_installation_note); + cur_frm.add_custom_button(wn._('Make Installation Note'), this.make_installation_note); if (doc.docstatus==1) { - cur_frm.add_custom_button('Send SMS', cur_frm.cscript.send_sms); + cur_frm.add_custom_button(wn._('Send SMS'), cur_frm.cscript.send_sms); this.show_stock_ledger(); this.show_general_ledger(); } if(doc.docstatus==0 && !doc.__islocal) { - cur_frm.add_custom_button('Make Packing Slip', cur_frm.cscript['Make Packing Slip']); + cur_frm.add_custom_button(wn._('Make Packing Slip'), cur_frm.cscript['Make Packing Slip']); } set_print_hide(doc, dt, dn); From 24ca7e4e2eb013be83cf6a20f099ff63754ec2a4 Mon Sep 17 00:00:00 2001 From: Rushabh Mehta Date: Wed, 2 Oct 2013 14:25:36 +0530 Subject: [PATCH 067/200] Added Transactions for Import webnotes/erpnext#911 --- .../purchase_invoice/purchase_invoice.txt | 3 +- .../doctype/sales_invoice/sales_invoice.txt | 3 +- .../doctype/purchase_order/purchase_order.txt | 4 +- .../supplier_quotation/supplier_quotation.txt | 3 +- .../production_order/production_order.txt | 3 +- projects/doctype/project/project.txt | 3 +- projects/doctype/task/task.txt | 3 +- selling/doctype/lead/lead.txt | 136 ++++++++---------- selling/doctype/opportunity/opportunity.txt | 8 +- selling/doctype/quotation/quotation.txt | 6 +- selling/doctype/sales_order/sales_order.txt | 3 +- .../material_request/material_request.txt | 3 +- 12 files changed, 85 insertions(+), 93 deletions(-) diff --git a/accounts/doctype/purchase_invoice/purchase_invoice.txt b/accounts/doctype/purchase_invoice/purchase_invoice.txt index f5bdd939a88..8f772272b75 100755 --- a/accounts/doctype/purchase_invoice/purchase_invoice.txt +++ b/accounts/doctype/purchase_invoice/purchase_invoice.txt @@ -2,12 +2,13 @@ { "creation": "2013-05-21 16:16:39", "docstatus": 0, - "modified": "2013-08-09 14:45:35", + "modified": "2013-10-02 14:24:55", "modified_by": "Administrator", "owner": "Administrator" }, { "allow_attach": 1, + "allow_import": 1, "autoname": "naming_series:", "doctype": "DocType", "icon": "icon-file-text", diff --git a/accounts/doctype/sales_invoice/sales_invoice.txt b/accounts/doctype/sales_invoice/sales_invoice.txt index f921f242234..3c9075d9a59 100644 --- a/accounts/doctype/sales_invoice/sales_invoice.txt +++ b/accounts/doctype/sales_invoice/sales_invoice.txt @@ -2,12 +2,13 @@ { "creation": "2013-05-24 19:29:05", "docstatus": 0, - "modified": "2013-09-01 05:26:13", + "modified": "2013-10-02 14:24:52", "modified_by": "Administrator", "owner": "Administrator" }, { "allow_attach": 1, + "allow_import": 1, "autoname": "naming_series:", "default_print_format": "Standard", "doctype": "DocType", diff --git a/buying/doctype/purchase_order/purchase_order.txt b/buying/doctype/purchase_order/purchase_order.txt index d3c1620b51d..7169aaf3906 100644 --- a/buying/doctype/purchase_order/purchase_order.txt +++ b/buying/doctype/purchase_order/purchase_order.txt @@ -2,12 +2,13 @@ { "creation": "2013-05-21 16:16:39", "docstatus": 0, - "modified": "2013-09-12 18:34:54", + "modified": "2013-10-02 14:24:49", "modified_by": "Administrator", "owner": "Administrator" }, { "allow_attach": 1, + "allow_import": 1, "autoname": "naming_series:", "doctype": "DocType", "document_type": "Transaction", @@ -132,7 +133,6 @@ "fieldtype": "Date", "in_filter": 1, "label": "Purchase Order Date", - "no_copy": 1, "oldfieldname": "transaction_date", "oldfieldtype": "Date", "reqd": 1, diff --git a/buying/doctype/supplier_quotation/supplier_quotation.txt b/buying/doctype/supplier_quotation/supplier_quotation.txt index 36747d345a8..ddd17307dcf 100644 --- a/buying/doctype/supplier_quotation/supplier_quotation.txt +++ b/buying/doctype/supplier_quotation/supplier_quotation.txt @@ -2,12 +2,13 @@ { "creation": "2013-05-21 16:16:45", "docstatus": 0, - "modified": "2013-08-09 14:45:58", + "modified": "2013-10-02 14:24:44", "modified_by": "Administrator", "owner": "Administrator" }, { "allow_attach": 1, + "allow_import": 1, "autoname": "naming_series:", "doctype": "DocType", "document_type": "Transaction", diff --git a/manufacturing/doctype/production_order/production_order.txt b/manufacturing/doctype/production_order/production_order.txt index 782c99f0363..81821f6c45c 100644 --- a/manufacturing/doctype/production_order/production_order.txt +++ b/manufacturing/doctype/production_order/production_order.txt @@ -2,11 +2,12 @@ { "creation": "2013-01-10 16:34:16", "docstatus": 0, - "modified": "2013-08-08 14:22:12", + "modified": "2013-10-02 14:25:03", "modified_by": "Administrator", "owner": "Administrator" }, { + "allow_import": 1, "autoname": "naming_series:", "doctype": "DocType", "icon": "icon-cogs", diff --git a/projects/doctype/project/project.txt b/projects/doctype/project/project.txt index 91dcfa16816..fc8accf1ee1 100644 --- a/projects/doctype/project/project.txt +++ b/projects/doctype/project/project.txt @@ -2,12 +2,13 @@ { "creation": "2013-03-07 11:55:07", "docstatus": 0, - "modified": "2013-07-05 14:51:41", + "modified": "2013-10-02 14:25:02", "modified_by": "Administrator", "owner": "Administrator" }, { "allow_attach": 1, + "allow_import": 1, "autoname": "field:project_name", "doctype": "DocType", "document_type": "Master", diff --git a/projects/doctype/task/task.txt b/projects/doctype/task/task.txt index d890bd67b94..1c12c8a534f 100644 --- a/projects/doctype/task/task.txt +++ b/projects/doctype/task/task.txt @@ -2,12 +2,13 @@ { "creation": "2013-01-29 19:25:50", "docstatus": 0, - "modified": "2013-07-05 14:57:57", + "modified": "2013-10-02 14:25:00", "modified_by": "Administrator", "owner": "Administrator" }, { "allow_attach": 1, + "allow_import": 1, "autoname": "TASK.#####", "doctype": "DocType", "document_type": "Master", diff --git a/selling/doctype/lead/lead.txt b/selling/doctype/lead/lead.txt index d96880bc755..9439e7854f8 100644 --- a/selling/doctype/lead/lead.txt +++ b/selling/doctype/lead/lead.txt @@ -2,11 +2,12 @@ { "creation": "2013-04-10 11:45:37", "docstatus": 0, - "modified": "2013-09-19 10:38:58", + "modified": "2013-10-02 14:24:34", "modified_by": "Administrator", "owner": "Administrator" }, { + "allow_import": 1, "autoname": "naming_series:", "doctype": "DocType", "document_type": "Master", @@ -158,76 +159,8 @@ "doctype": "DocField", "fieldname": "communication_history", "fieldtype": "Section Break", - "label": "Communication", - "options": "icon-comments", - "print_hide": 1 - }, - { - "default": "__user", - "doctype": "DocField", - "fieldname": "lead_owner", - "fieldtype": "Link", - "in_filter": 1, - "label": "Lead Owner", - "oldfieldname": "lead_owner", - "oldfieldtype": "Link", - "options": "Profile", - "search_index": 1 - }, - { - "depends_on": "eval:!doc.__islocal", - "description": "Date on which the lead was last contacted", - "doctype": "DocField", - "fieldname": "last_contact_date", - "fieldtype": "Date", - "label": "Last Contact Date", - "no_copy": 1, - "oldfieldname": "last_contact_date", - "oldfieldtype": "Date", - "print_hide": 1, - "read_only": 1 - }, - { - "doctype": "DocField", - "fieldname": "col_break123", - "fieldtype": "Column Break", - "width": "50%" - }, - { - "allow_on_submit": 0, - "description": "Your sales person who will contact the lead in future", - "doctype": "DocField", - "fieldname": "contact_by", - "fieldtype": "Link", - "hidden": 0, - "in_filter": 1, - "label": "Next Contact By", - "oldfieldname": "contact_by", - "oldfieldtype": "Link", - "options": "Profile", - "print_hide": 0, - "reqd": 0, - "width": "100px" - }, - { - "allow_on_submit": 0, - "description": "Your sales person will get a reminder on this date to contact the lead", - "doctype": "DocField", - "fieldname": "contact_date", - "fieldtype": "Date", - "in_filter": 1, - "label": "Next Contact Date", - "no_copy": 1, - "oldfieldname": "contact_date", - "oldfieldtype": "Date", - "reqd": 0, - "width": "100px" - }, - { - "doctype": "DocField", - "fieldname": "sec_break123", - "fieldtype": "Section Break", - "options": "Simple" + "label": "Communication History", + "options": "icon-comments" }, { "allow_on_submit": 0, @@ -236,8 +169,7 @@ "fieldtype": "HTML", "label": "Communication HTML", "oldfieldname": "follow_up", - "oldfieldtype": "Table", - "print_hide": 1 + "oldfieldtype": "Table" }, { "doctype": "DocField", @@ -341,6 +273,18 @@ "oldfieldtype": "Select", "options": "\nClient\nChannel Partner\nConsultant" }, + { + "default": "__user", + "doctype": "DocField", + "fieldname": "lead_owner", + "fieldtype": "Link", + "in_filter": 1, + "label": "Lead Owner", + "oldfieldname": "lead_owner", + "oldfieldtype": "Link", + "options": "Profile", + "search_index": 1 + }, { "doctype": "DocField", "fieldname": "market_segment", @@ -402,6 +346,49 @@ "oldfieldtype": "Link", "options": "Quotation Lost Reason" }, + { + "allow_on_submit": 0, + "description": "Your sales person who will contact the lead in future", + "doctype": "DocField", + "fieldname": "contact_by", + "fieldtype": "Link", + "hidden": 0, + "in_filter": 1, + "label": "Next Contact By", + "oldfieldname": "contact_by", + "oldfieldtype": "Link", + "options": "Profile", + "print_hide": 0, + "reqd": 0, + "width": "100px" + }, + { + "allow_on_submit": 0, + "description": "Your sales person will get a reminder on this date to contact the lead", + "doctype": "DocField", + "fieldname": "contact_date", + "fieldtype": "Date", + "in_filter": 1, + "label": "Next Contact Date", + "no_copy": 1, + "oldfieldname": "contact_date", + "oldfieldtype": "Date", + "reqd": 0, + "width": "100px" + }, + { + "depends_on": "eval:!doc.__islocal", + "description": "Date on which the lead was last contacted", + "doctype": "DocField", + "fieldname": "last_contact_date", + "fieldtype": "Date", + "label": "Last Contact Date", + "no_copy": 1, + "oldfieldname": "last_contact_date", + "oldfieldtype": "Date", + "print_hide": 1, + "read_only": 1 + }, { "doctype": "DocField", "fieldname": "company", @@ -430,8 +417,7 @@ "fieldtype": "Table", "hidden": 1, "label": "Communications", - "options": "Communication", - "print_hide": 1 + "options": "Communication" }, { "cancel": 1, diff --git a/selling/doctype/opportunity/opportunity.txt b/selling/doctype/opportunity/opportunity.txt index a904f566439..d39b3efdae1 100644 --- a/selling/doctype/opportunity/opportunity.txt +++ b/selling/doctype/opportunity/opportunity.txt @@ -2,11 +2,12 @@ { "creation": "2013-03-07 18:50:30", "docstatus": 0, - "modified": "2013-09-10 10:52:49", + "modified": "2013-10-02 14:24:35", "modified_by": "Administrator", "owner": "Administrator" }, { + "allow_import": 1, "autoname": "naming_series:", "description": "Potential Sales Deal", "doctype": "DocType", @@ -168,7 +169,6 @@ "label": "Communication History", "oldfieldtype": "Section Break", "options": "icon-comments", - "print_hide": 1, "read_only": 0 }, { @@ -179,7 +179,6 @@ "label": "Communication HTML", "oldfieldname": "follow_up", "oldfieldtype": "Table", - "print_hide": 1, "read_only": 0 }, { @@ -450,8 +449,7 @@ "fieldtype": "Table", "hidden": 1, "label": "Communications", - "options": "Communication", - "print_hide": 1 + "options": "Communication" }, { "doctype": "DocPerm", diff --git a/selling/doctype/quotation/quotation.txt b/selling/doctype/quotation/quotation.txt index 3f97c980bc4..200627f794f 100644 --- a/selling/doctype/quotation/quotation.txt +++ b/selling/doctype/quotation/quotation.txt @@ -2,13 +2,14 @@ { "creation": "2013-05-24 19:29:08", "docstatus": 0, - "modified": "2013-09-10 10:46:33", + "modified": "2013-10-02 14:24:35", "modified_by": "Administrator", "owner": "Administrator" }, { "allow_attach": 1, "allow_email": 0, + "allow_import": 1, "autoname": "naming_series:", "doctype": "DocType", "document_type": "Transaction", @@ -841,8 +842,7 @@ "fieldtype": "Table", "hidden": 1, "label": "Communications", - "options": "Communication", - "print_hide": 1 + "options": "Communication" }, { "amend": 1, diff --git a/selling/doctype/sales_order/sales_order.txt b/selling/doctype/sales_order/sales_order.txt index 94e63888e3b..366aa8e7903 100644 --- a/selling/doctype/sales_order/sales_order.txt +++ b/selling/doctype/sales_order/sales_order.txt @@ -2,12 +2,13 @@ { "creation": "2013-06-18 12:39:59", "docstatus": 0, - "modified": "2013-08-09 14:46:17", + "modified": "2013-10-02 14:24:37", "modified_by": "Administrator", "owner": "Administrator" }, { "allow_attach": 1, + "allow_import": 1, "autoname": "naming_series:", "doctype": "DocType", "document_type": "Transaction", diff --git a/stock/doctype/material_request/material_request.txt b/stock/doctype/material_request/material_request.txt index a5f092d7cbb..5fd576aab66 100644 --- a/stock/doctype/material_request/material_request.txt +++ b/stock/doctype/material_request/material_request.txt @@ -2,12 +2,13 @@ { "creation": "2013-03-07 14:48:38", "docstatus": 0, - "modified": "2013-08-08 14:22:27", + "modified": "2013-10-02 14:24:42", "modified_by": "Administrator", "owner": "Administrator" }, { "allow_attach": 1, + "allow_import": 1, "allow_print": 0, "autoname": "naming_series:", "doctype": "DocType", From 8c2e4e1e1f8892775e0afb77fe8f4002728a60be Mon Sep 17 00:00:00 2001 From: Rushabh Mehta Date: Wed, 2 Oct 2013 14:34:25 +0530 Subject: [PATCH 068/200] [wsgi] [minor] fixed webnotes.local.form_dict --- accounts/page/accounts_browser/accounts_browser.py | 2 +- accounts/utils.py | 4 ++-- hr/doctype/upload_attendance/upload_attendance.py | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/accounts/page/accounts_browser/accounts_browser.py b/accounts/page/accounts_browser/accounts_browser.py index 61f4bfc521b..7bc95494128 100644 --- a/accounts/page/accounts_browser/accounts_browser.py +++ b/accounts/page/accounts_browser/accounts_browser.py @@ -15,7 +15,7 @@ def get_companies(): @webnotes.whitelist() def get_children(): - args = webnotes.form_dict + args = webnotes.local.form_dict ctype, company = args['ctype'], args['comp'] # root diff --git a/accounts/utils.py b/accounts/utils.py index 5c6c16b76a9..ac823129d66 100644 --- a/accounts/utils.py +++ b/accounts/utils.py @@ -108,7 +108,7 @@ def get_balance_on(account=None, date=None): @webnotes.whitelist() def add_ac(args=None): if not args: - args = webnotes.form_dict + args = webnotes.local.form_dict args.pop("cmd") ac = webnotes.bean(args) @@ -121,7 +121,7 @@ def add_ac(args=None): @webnotes.whitelist() def add_cc(args=None): if not args: - args = webnotes.form_dict + args = webnotes.local.form_dict args.pop("cmd") cc = webnotes.bean(args) diff --git a/hr/doctype/upload_attendance/upload_attendance.py b/hr/doctype/upload_attendance/upload_attendance.py index 5e2b02ea1fd..56c8eedcc75 100644 --- a/hr/doctype/upload_attendance/upload_attendance.py +++ b/hr/doctype/upload_attendance/upload_attendance.py @@ -22,7 +22,7 @@ def get_template(): if not webnotes.has_permission("Attendance", "create"): raise webnotes.PermissionError - args = webnotes.form_dict + args = webnotes.local.form_dict webnotes.local.uploadattendance_doclist = webnotes.model.doctype.get("Attendance") w = UnicodeWriter() From ea9f845814190e189e63e9b0692f17d2a02fba63 Mon Sep 17 00:00:00 2001 From: Rushabh Mehta Date: Wed, 2 Oct 2013 16:02:02 +0530 Subject: [PATCH 069/200] feature to set / unset birthday reminders webnotes/erpnext#851 --- hr/doctype/employee/employee.py | 9 +++++---- hr/doctype/hr_settings/hr_settings.py | 20 +++++++++++++++++++- hr/doctype/hr_settings/hr_settings.txt | 21 ++++++++++++++++++++- 3 files changed, 44 insertions(+), 6 deletions(-) diff --git a/hr/doctype/employee/employee.py b/hr/doctype/employee/employee.py index e8396eb5392..b46123a6d1f 100644 --- a/hr/doctype/employee/employee.py +++ b/hr/doctype/employee/employee.py @@ -4,7 +4,7 @@ from __future__ import unicode_literals import webnotes -from webnotes.utils import getdate, validate_email_add, cstr +from webnotes.utils import getdate, validate_email_add, cstr, cint from webnotes.model.doc import make_autoname from webnotes import msgprint, _ @@ -39,12 +39,12 @@ class DocType: self.validate_email() self.validate_status() self.validate_employee_leave_approver() + self.update_dob_event() def on_update(self): if self.doc.user_id: self.update_user_default() self.update_profile() - self.update_dob_event() def update_user_default(self): webnotes.conn.set_default("employee", self.doc.name, self.doc.user_id) @@ -155,10 +155,11 @@ class DocType: raise_exception=InvalidLeaveApproverError) def update_dob_event(self): - if self.doc.status == "Active" and self.doc.date_of_birth: + if self.doc.status == "Active" and self.doc.date_of_birth \ + and not cint(webnotes.conn.get_value("HR Settings", None, "stop_birthday_reminders")): birthday_event = webnotes.conn.sql("""select name from `tabEvent` where repeat_on='Every Year' and ref_type='Employee' and ref_name=%s""", self.doc.name) - + starts_on = self.doc.date_of_birth + " 00:00:00" ends_on = self.doc.date_of_birth + " 00:15:00" diff --git a/hr/doctype/hr_settings/hr_settings.py b/hr/doctype/hr_settings/hr_settings.py index 784339de7db..101905c57b4 100644 --- a/hr/doctype/hr_settings/hr_settings.py +++ b/hr/doctype/hr_settings/hr_settings.py @@ -6,6 +6,24 @@ from __future__ import unicode_literals import webnotes +from webnotes.utils import cint + class DocType: def __init__(self, d, dl): - self.doc, self.doclist = d, dl \ No newline at end of file + self.doc, self.doclist = d, dl + + def validate(self): + self.original_stop_birthday_reminders = cint(webnotes.conn.get_value("HR Settings", + None, "stop_birthday_reminders")) + + def on_update(self): + # reset birthday reminders + if cint(self.doc.stop_birthday_reminders) != self.original_stop_birthday_reminders: + webnotes.conn.sql("""delete from `tabEvent` where repeat_on='Every Year' and ref_type='Employee'""") + + if not self.doc.stop_birthday_reminders: + for employee in webnotes.conn.sql_list("""select name from `tabEmployee` where status='Active' and + ifnull(date_of_birth, '')!=''"""): + webnotes.get_obj("Employee", employee).update_dob_event() + + webnotes.msgprint(webnotes._("Updated Birthday Reminders")) \ No newline at end of file diff --git a/hr/doctype/hr_settings/hr_settings.txt b/hr/doctype/hr_settings/hr_settings.txt index e3694d05727..bf4b0119aaf 100644 --- a/hr/doctype/hr_settings/hr_settings.txt +++ b/hr/doctype/hr_settings/hr_settings.txt @@ -2,7 +2,7 @@ { "creation": "2013-08-02 13:45:23", "docstatus": 0, - "modified": "2013-08-02 14:22:26", + "modified": "2013-10-02 15:44:38", "modified_by": "Administrator", "owner": "Administrator" }, @@ -38,6 +38,12 @@ "doctype": "DocType", "name": "HR Settings" }, + { + "doctype": "DocField", + "fieldname": "employee_settings", + "fieldtype": "Section Break", + "label": "Employee Settings" + }, { "description": "Employee record is created using selected field. ", "doctype": "DocField", @@ -46,6 +52,19 @@ "label": "Employee Records to be created by", "options": "Naming Series\nEmployee Number" }, + { + "description": "Don't send Employee Birthday Reminders", + "doctype": "DocField", + "fieldname": "stop_birthday_reminders", + "fieldtype": "Check", + "label": "Stop Birthday Reminders" + }, + { + "doctype": "DocField", + "fieldname": "payroll_settings", + "fieldtype": "Section Break", + "label": "Payroll Settings" + }, { "description": "If checked, Total no. of Working Days will include holidays, and this will reduce the value of Salary Per Day", "doctype": "DocField", From f1b6f67a98c4877e7052e4cd13ff0112d3758237 Mon Sep 17 00:00:00 2001 From: Rushabh Mehta Date: Thu, 3 Oct 2013 12:22:52 +0530 Subject: [PATCH 070/200] [Delivery Note] Moved prevdoc to Sales Order and Sales Invoice so links will work webnotes/erpnext#868 --- .../doctype/sales_invoice/sales_invoice.py | 3 +- .../p01_update_delivery_note_prevdocs.py | 12 +++++ patches/patch_list.py | 1 + selling/doctype/sales_common/sales_common.py | 29 ++++++----- selling/doctype/sales_order/sales_order.py | 3 +- .../doctype/sales_order/test_sales_order.py | 3 +- stock/doctype/delivery_note/delivery_note.js | 10 ++-- stock/doctype/delivery_note/delivery_note.py | 49 ++++++++++--------- .../delivery_note_item/delivery_note_item.txt | 47 ++++++++---------- stock/doctype/stock_entry/stock_entry.py | 3 +- 10 files changed, 85 insertions(+), 75 deletions(-) create mode 100644 patches/october_2013/p01_update_delivery_note_prevdocs.py diff --git a/accounts/doctype/sales_invoice/sales_invoice.py b/accounts/doctype/sales_invoice/sales_invoice.py index 2eb9ae84cb0..1dca77b3fba 100644 --- a/accounts/doctype/sales_invoice/sales_invoice.py +++ b/accounts/doctype/sales_invoice/sales_invoice.py @@ -965,8 +965,7 @@ def make_delivery_note(source_name, target_doclist=None): "doctype": "Delivery Note Item", "field_map": { "name": "prevdoc_detail_docname", - "parent": "prevdoc_docname", - "parenttype": "prevdoc_doctype", + "parent": "against_sales_invoice", "serial_no": "serial_no" }, "postprocess": update_item diff --git a/patches/october_2013/p01_update_delivery_note_prevdocs.py b/patches/october_2013/p01_update_delivery_note_prevdocs.py new file mode 100644 index 00000000000..b1a16c28beb --- /dev/null +++ b/patches/october_2013/p01_update_delivery_note_prevdocs.py @@ -0,0 +1,12 @@ +# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. +# License: GNU General Public License v3. See license.txt + +from __future__ import unicode_literals +import webnotes + +def execute(): + webnotes.conn.sql("""update `tabDelivery Note Item` set against_sales_order=prevdoc_docname + where prevdoc_doctype='Sales Order' """) + + webnotes.conn.sql("""update `tabDelivery Note Item` set against_sales_invoice=prevdoc_docname + where prevdoc_doctype='Sales Invoice' """) \ No newline at end of file diff --git a/patches/patch_list.py b/patches/patch_list.py index f228acf97e7..e19afdaf5ca 100644 --- a/patches/patch_list.py +++ b/patches/patch_list.py @@ -220,4 +220,5 @@ patch_list = [ "patches.september_2013.p04_unsubmit_serial_nos", "patches.september_2013.p05_fix_customer_in_pos", "patches.october_2013.fix_is_cancelled_in_sle", + "patches.october_2013.p01_update_delivery_note_prevdocs", ] \ No newline at end of file diff --git a/selling/doctype/sales_common/sales_common.py b/selling/doctype/sales_common/sales_common.py index 8271c828740..df7f1511493 100644 --- a/selling/doctype/sales_common/sales_common.py +++ b/selling/doctype/sales_common/sales_common.py @@ -123,12 +123,12 @@ class DocType(TransactionBase): if flt(d.qty) > flt(d.delivered_qty): reserved_qty_for_main_item = flt(d.qty) - flt(d.delivered_qty) - if obj.doc.doctype == "Delivery Note" and d.prevdoc_doctype == 'Sales Order': + if obj.doc.doctype == "Delivery Note" and d.against_sales_order: # if SO qty is 10 and there is tolerance of 20%, then it will allow DN of 12. # But in this case reserved qty should only be reduced by 10 and not 12 already_delivered_qty = self.get_already_delivered_qty(obj.doc.name, - d.prevdoc_docname, d.prevdoc_detail_docname) + d.against_sales_order, d.prevdoc_detail_docname) so_qty, reserved_warehouse = self.get_so_qty_and_warehouse(d.prevdoc_detail_docname) if already_delivered_qty + d.qty > so_qty: @@ -168,7 +168,7 @@ class DocType(TransactionBase): def get_already_delivered_qty(self, dn, so, so_detail): qty = webnotes.conn.sql("""select sum(qty) from `tabDelivery Note Item` where prevdoc_detail_docname = %s and docstatus = 1 - and prevdoc_doctype = 'Sales Order' and prevdoc_docname = %s + and against_sales_order = %s and parent != %s""", (so_detail, so, dn)) return qty and flt(qty[0][0]) or 0.0 @@ -218,7 +218,6 @@ class DocType(TransactionBase): pi.qty = flt(qty) pi.actual_qty = bin and flt(bin['actual_qty']) or 0 pi.projected_qty = bin and flt(bin['projected_qty']) or 0 - pi.prevdoc_doctype = line.prevdoc_doctype if not pi.warehouse: pi.warehouse = warehouse if not pi.batch_no: @@ -283,8 +282,8 @@ class DocType(TransactionBase): def check_stop_sales_order(self,obj): for d in getlist(obj.doclist,obj.fname): ref_doc_name = '' - if d.fields.has_key('prevdoc_docname') and d.prevdoc_docname and d.prevdoc_doctype == 'Sales Order': - ref_doc_name = d.prevdoc_docname + if d.fields.has_key('against_sales_order') and d.against_sales_order: + ref_doc_name = d.against_sales_order elif d.fields.has_key('sales_order') and d.sales_order and not d.delivery_note: ref_doc_name = d.sales_order if ref_doc_name: @@ -321,14 +320,22 @@ class DocType(TransactionBase): def get_prevdoc_date(self, obj): for d in getlist(obj.doclist, obj.fname): - if d.prevdoc_doctype and d.prevdoc_docname: - if d.prevdoc_doctype in ["Sales Invoice", "Delivery Note"]: + date_field = None + + pdoctype, pname = d.prevdoc_doctype, d.prevdoc_docname + + if d.against_sales_invoice: + pdoctype, pname = "Sales Invoice", d.against_sales_invoice + elif d.against_sales_order: + pdoctype, pname = "Sales Order", d.against_sales_order + + if pdoctype and pname: + if pdoctype in ["Sales Invoice", "Delivery Note"]: date_field = "posting_date" else: date_field = "transaction_date" - - d.prevdoc_date = webnotes.conn.get_value(d.prevdoc_doctype, - d.prevdoc_docname, date_field) + + d.prevdoc_date = webnotes.conn.get_value(pdoctype, pname, date_field) def get_batch_no(doctype, txt, searchfield, start, page_len, filters): from controllers.queries import get_match_cond diff --git a/selling/doctype/sales_order/sales_order.py b/selling/doctype/sales_order/sales_order.py index 40567429cc6..8fc728fccdc 100644 --- a/selling/doctype/sales_order/sales_order.py +++ b/selling/doctype/sales_order/sales_order.py @@ -341,8 +341,7 @@ def make_delivery_note(source_name, target_doclist=None): "field_map": { "export_rate": "export_rate", "name": "prevdoc_detail_docname", - "parent": "prevdoc_docname", - "parenttype": "prevdoc_doctype", + "parent": "against_sales_order", "reserved_warehouse": "warehouse" }, "postprocess": update_item, diff --git a/selling/doctype/sales_order/test_sales_order.py b/selling/doctype/sales_order/test_sales_order.py index 7b72271bec9..8bd759a77da 100644 --- a/selling/doctype/sales_order/test_sales_order.py +++ b/selling/doctype/sales_order/test_sales_order.py @@ -74,8 +74,7 @@ class TestSalesOrder(unittest.TestCase): from stock.doctype.delivery_note.test_delivery_note import test_records as dn_test_records dn = webnotes.bean(webnotes.copy_doclist(dn_test_records[0])) dn.doclist[1].item_code = so.doclist[1].item_code - dn.doclist[1].prevdoc_doctype = "Sales Order" - dn.doclist[1].prevdoc_docname = so.doc.name + dn.doclist[1].against_sales_order = so.doc.name dn.doclist[1].prevdoc_detail_docname = so.doclist[1].name if delivered_qty: dn.doclist[1].qty = delivered_qty diff --git a/stock/doctype/delivery_note/delivery_note.js b/stock/doctype/delivery_note/delivery_note.js index 84e65dabddf..edfd6ff7db2 100644 --- a/stock/doctype/delivery_note/delivery_note.js +++ b/stock/doctype/delivery_note/delivery_note.js @@ -22,7 +22,7 @@ erpnext.stock.DeliveryNoteController = erpnext.selling.SellingController.extend( var from_sales_invoice = false; from_sales_invoice = cur_frm.get_doclist({parentfield: "delivery_note_details"}) .some(function(item) { - return item.prevdoc_doctype==="Sales Invoice" ? true : false; + return item.against_sales_invoice ? true : false; }); if(!from_sales_invoice) @@ -181,12 +181,12 @@ cur_frm.pformat.sales_order_no= function(doc, cdt, cdn){ if(cl.length){ prevdoc_list = new Array(); for(var i=0;i Date: Thu, 3 Oct 2013 13:19:51 +0530 Subject: [PATCH 071/200] [minor] [fix] [demo] --- utilities/demo/make_demo.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/utilities/demo/make_demo.py b/utilities/demo/make_demo.py index 4f30df62be3..692ae311105 100644 --- a/utilities/demo/make_demo.py +++ b/utilities/demo/make_demo.py @@ -40,7 +40,9 @@ def make(reset=False, simulate=True): if reset: setup() else: - webnotes.conn.close() + if webnotes.conn: + webnotes.conn.close() + webnotes.connect(db_name=webnotes.conf.demo_db_name) if simulate: From 43247cedea3baf6928ff692ec44767c32df5afca Mon Sep 17 00:00:00 2001 From: Rushabh Mehta Date: Thu, 3 Oct 2013 14:50:55 +0530 Subject: [PATCH 072/200] [issues] [minor] fixed multiple minor issues --- setup/doctype/sales_partner/sales_partner.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/setup/doctype/sales_partner/sales_partner.py b/setup/doctype/sales_partner/sales_partner.py index 79a59db71a3..9e3e2a82351 100644 --- a/setup/doctype/sales_partner/sales_partner.py +++ b/setup/doctype/sales_partner/sales_partner.py @@ -11,6 +11,10 @@ class DocType: self.doc = doc self.doclist = doclist + def validate(self): + if self.doc.partner_website and not self.doc.partner_website.startswith("http"): + self.doc.partner_website = "http://" + self.doc.partner_website + def on_update(self): if cint(self.doc.show_in_website): from webnotes.webutils import update_page_name From 800b3aa437aa0196f77c934f1443b4bff8b75ffb Mon Sep 17 00:00:00 2001 From: Rushabh Mehta Date: Thu, 3 Oct 2013 17:26:33 +0530 Subject: [PATCH 073/200] [crm] Updated status and workflow for Lead > Opportunity > Quotation > Sales Order --- controllers/selling_controller.py | 5 +- controllers/status_updater.py | 78 +++++++++++++++++++ hr/doctype/job_applicant/job_applicant.py | 15 ++-- .../p02_set_communication_status.py | 9 +++ patches/october_2013/p03_crm_update_status.py | 32 ++++++++ patches/patch_list.py | 2 + selling/doctype/lead/lead.py | 27 ++----- selling/doctype/lead/lead.txt | 18 +---- selling/doctype/opportunity/opportunity.js | 15 +--- selling/doctype/opportunity/opportunity.py | 43 ++++------ selling/doctype/opportunity/opportunity.txt | 25 +++--- selling/doctype/quotation/quotation.js | 13 +--- selling/doctype/quotation/quotation.py | 64 +++++---------- selling/doctype/quotation/quotation.txt | 4 +- selling/doctype/sales_order/sales_order.js | 2 +- selling/doctype/sales_order/sales_order.py | 30 ++----- .../support_ticket/get_support_mails.py | 2 +- .../doctype/support_ticket/support_ticket.py | 13 +--- .../doctype/support_ticket/support_ticket.txt | 4 +- utilities/doctype/contact/contact.py | 9 +-- utilities/doctype/contact/contact.txt | 5 +- 21 files changed, 213 insertions(+), 202 deletions(-) create mode 100644 patches/october_2013/p02_set_communication_status.py create mode 100644 patches/october_2013/p03_crm_update_status.py diff --git a/controllers/selling_controller.py b/controllers/selling_controller.py index f1117ed177b..2816524160e 100644 --- a/controllers/selling_controller.py +++ b/controllers/selling_controller.py @@ -14,7 +14,10 @@ class SellingController(StockController): def onload_post_render(self): # contact, address, item details and pos details (if applicable) self.set_missing_values() - + + def get_sender(self, comm): + return webnotes.conn.get_value('Sales Email Settings', None, 'email_id') + def set_missing_values(self, for_validate=False): super(SellingController, self).set_missing_values(for_validate) diff --git a/controllers/status_updater.py b/controllers/status_updater.py index 070f2002764..07b812a7dc1 100644 --- a/controllers/status_updater.py +++ b/controllers/status_updater.py @@ -8,6 +8,51 @@ from webnotes import msgprint from webnotes.model.controller import DocListController +status_map = { + "Contact": [ + ["Replied", "communication_sent"], + ["Open", "communication_received"] + ], + "Job Applicant": [ + ["Replied", "communication_sent"], + ["Open", "communication_received"] + ], + "Lead": [ + ["Replied", "communication_sent"], + ["Converted", "has_customer"], + ["Opportunity", "has_opportunity"], + ["Open", "communication_received"], + ], + "Opportunity": [ + ["Draft", None], + ["Submitted", "eval:self.doc.docstatus==1"], + ["Lost", "eval:self.doc.status=='Lost'"], + ["Quotation", "has_quotation"], + ["Replied", "communication_sent"], + ["Cancelled", "eval:self.doc.docstatus==2"], + ["Open", "communication_received"], + ], + "Quotation": [ + ["Draft", None], + ["Submitted", "eval:self.doc.docstatus==1"], + ["Lost", "eval:self.doc.status=='Lost'"], + ["Ordered", "has_sales_order"], + ["Replied", "communication_sent"], + ["Cancelled", "eval:self.doc.docstatus==2"], + ["Open", "communication_received"], + ], + "Sales Order": [ + ["Draft", None], + ["Submitted", "eval:self.doc.docstatus==1"], + ["Stopped", "eval:self.doc.status=='Stopped'"], + ["Cancelled", "eval:self.doc.docstatus==2"], + ], + "Support Ticket": [ + ["Replied", "communication_sent"], + ["Open", "communication_received"] + ], +} + class StatusUpdater(DocListController): """ Updates the status of the calling records @@ -20,6 +65,39 @@ class StatusUpdater(DocListController): self.update_qty() self.validate_qty() + def set_status(self, update=False): + if self.doc.get("__islocal"): + return + + if self.doc.doctype in status_map.keys(): + for s in status_map[self.doc.doctype].reverse(): + if not s[1]: + self.doc.status = s[0] + break + elif s[1].startwith("eval:"): + if eval(s[1][5:]): + self.doc.status = s[0] + break + elif getattr(self, s[1])(): + self.doc.status = s[0] + break + + if update: + webnotes.conn.set_value(self.doc.doctype, self.doc.name, "status", self.doc.status) + + def on_communication(self): + self.set_status(update=True) + + def communication_received(self): + last_comm = self.doclist.get({"doctype":"Communication"})[-1] + if last_comm: + return last_comm.sent_or_received == "Received" + + def communication_sent(self): + last_comm = self.doclist.get({"doctype":"Communication"})[-1] + if last_comm: + return last_comm.sent_or_received == "Sent" + def validate_qty(self): """ Validates qty at row level diff --git a/hr/doctype/job_applicant/job_applicant.py b/hr/doctype/job_applicant/job_applicant.py index 9bf1b967e7d..0ab4ba86128 100644 --- a/hr/doctype/job_applicant/job_applicant.py +++ b/hr/doctype/job_applicant/job_applicant.py @@ -11,14 +11,9 @@ from webnotes.utils import extract_email_id class DocType(TransactionBase): def __init__(self, d, dl): self.doc, self.doclist = d, dl - + def get_sender(self, comm): - return webnotes.conn.get_value('Jobs Email Settings',None,'email_id') - - def on_communication(self, comm): - if webnotes.conn.get_value("Profile", extract_email_id(comm.sender), "user_type")=="System User": - status = "Replied" - else: - status = "Open" - - webnotes.conn.set(self.doc, 'status', status) \ No newline at end of file + return webnotes.conn.get_value('Jobs Email Settings',None,'email_id') + + def validate(self): + self.set_status() \ No newline at end of file diff --git a/patches/october_2013/p02_set_communication_status.py b/patches/october_2013/p02_set_communication_status.py new file mode 100644 index 00000000000..8360fe6ceeb --- /dev/null +++ b/patches/october_2013/p02_set_communication_status.py @@ -0,0 +1,9 @@ +# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. +# License: GNU General Public License v3. See license.txt + +from __future__ import unicode_literals +import webnotes + +def execute(): + webnotes.conn.sql("""update tabCommunication + set sent_or_received= if(ifnull(recipients, '')='', "Received", "Sent")""") \ No newline at end of file diff --git a/patches/october_2013/p03_crm_update_status.py b/patches/october_2013/p03_crm_update_status.py new file mode 100644 index 00000000000..e5b434ce1ff --- /dev/null +++ b/patches/october_2013/p03_crm_update_status.py @@ -0,0 +1,32 @@ +# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. +# License: GNU General Public License v3. See license.txt + +from __future__ import unicode_literals +import webnotes + +# reason field + +def execute(): + change_map = { + "Lead": [ + ["Lead Lost", "Lead"], + ["Not interested", "Do Not Contact"], + ["Opportunity Made", "Opportunity"], + ["Contacted", "Replied"], + ["Attempted to Contact", "Replied"], + ["Contact in Future", "Interested"], + ], + "Opportunity": [ + ["Quotation Sent", "Quotation"], + ["Order Confirmed", "Quotation"], + ["Opportunity Lost", "Lost"], + ], + "Quotation": [ + ["Order Confirmed", "Ordered"], + ["Order Lost", "Lost"] + ], + "Support Ticket": [ + ["Waiting for Customer", "Replied"], + ["To Reply", "Open"], + ] + } \ No newline at end of file diff --git a/patches/patch_list.py b/patches/patch_list.py index e19afdaf5ca..1596a2870b1 100644 --- a/patches/patch_list.py +++ b/patches/patch_list.py @@ -221,4 +221,6 @@ patch_list = [ "patches.september_2013.p05_fix_customer_in_pos", "patches.october_2013.fix_is_cancelled_in_sle", "patches.october_2013.p01_update_delivery_note_prevdocs", + "patches.october_2013.p02_set_communication_status", + "patches.october_2013.p03_crm_update_status", ] \ No newline at end of file diff --git a/selling/doctype/lead/lead.py b/selling/doctype/lead/lead.py index 7a37446bf1b..b42a3807582 100644 --- a/selling/doctype/lead/lead.py +++ b/selling/doctype/lead/lead.py @@ -26,24 +26,9 @@ class DocType(SellingController): customer = webnotes.conn.get_value("Customer", {"lead_name": self.doc.name}) if customer: self.doc.fields["__is_customer"] = customer - - def on_communication(self, comm): - if comm.sender == self.get_sender(comm) or \ - webnotes.conn.get_value("Profile", extract_email_id(comm.sender), "user_type")=="System User": - status = "Replied" - else: - status = "Open" - - webnotes.conn.set(self.doc, 'status', status) - - def check_status(self): - chk = webnotes.conn.sql("select status from `tabLead` where name=%s", self.doc.name) - chk = chk and chk[0][0] or '' - return cstr(chk) def validate(self): - if self.doc.status == 'Lead Lost' and not self.doc.order_lost_reason: - webnotes.throw("Please Enter Lost Reason under More Info section") + self.set_status() if self.doc.source == 'Campaign' and not self.doc.campaign_name and session['user'] != 'Guest': webnotes.throw("Please specify campaign name") @@ -75,14 +60,18 @@ class DocType(SellingController): webnotes.msgprint(_("""Email Id must be unique, already exists for: """) + \ ", ".join(items), raise_exception=True) - def get_sender(self, comm): - return webnotes.conn.get_value('Sales Email Settings',None,'email_id') - def on_trash(self): webnotes.conn.sql("""update `tabSupport Ticket` set lead='' where lead=%s""", self.doc.name) self.delete_events() + + def has_customer(self): + return webnotes.conn.get_value("Customer", {"lead_name": self.doc.name}) + + def has_opportunity(self): + return webnotes.conn.get_value("Opportunity", {"lead": self.doc.name, "docstatus": 1, + "status": ["!=", "Lost"]}) @webnotes.whitelist() def make_customer(source_name, target_doclist=None): diff --git a/selling/doctype/lead/lead.txt b/selling/doctype/lead/lead.txt index 6044f7994b4..4f481b0a5e4 100644 --- a/selling/doctype/lead/lead.txt +++ b/selling/doctype/lead/lead.txt @@ -2,7 +2,7 @@ { "creation": "2013-04-10 11:45:37", "docstatus": 0, - "modified": "2013-10-02 14:24:30", + "modified": "2013-10-03 17:24:33", "modified_by": "Administrator", "owner": "Administrator" }, @@ -102,7 +102,7 @@ "fieldtype": "Column Break" }, { - "default": "Open", + "default": "Lead", "doctype": "DocField", "fieldname": "status", "fieldtype": "Select", @@ -112,7 +112,7 @@ "no_copy": 1, "oldfieldname": "status", "oldfieldtype": "Select", - "options": "\nOpen\nReplied\nAttempted to Contact\nContact in Future\nContacted\nOpportunity Made\nInterested\nNot interested\nLead Lost\nConverted\nPassive", + "options": "Lead\nOpen\nReplied\nOpportunity\nInterested\nConverted\nDo Not Contact", "reqd": 1, "search_index": 1 }, @@ -334,18 +334,6 @@ "oldfieldtype": "Column Break", "width": "50%" }, - { - "allow_on_submit": 0, - "depends_on": "eval:doc.status == 'Lead Lost'", - "doctype": "DocField", - "fieldname": "order_lost_reason", - "fieldtype": "Link", - "hidden": 0, - "label": "Lost Reason", - "oldfieldname": "order_lost_reason", - "oldfieldtype": "Link", - "options": "Quotation Lost Reason" - }, { "allow_on_submit": 0, "description": "Your sales person who will contact the lead in future", diff --git a/selling/doctype/opportunity/opportunity.js b/selling/doctype/opportunity/opportunity.js index 25f28bf3fbf..d2b866cfbbf 100644 --- a/selling/doctype/opportunity/opportunity.js +++ b/selling/doctype/opportunity/opportunity.js @@ -101,20 +101,13 @@ $.extend(cur_frm.cscript, new erpnext.selling.Opportunity({frm: cur_frm})); cur_frm.cscript.refresh = function(doc, cdt, cdn){ erpnext.hide_naming_series(); - - cur_frm.dashboard.reset(doc); - if(!doc.__islocal) { - if(doc.status=="Converted" || doc.status=="Order Confirmed") { - cur_frm.dashboard.set_headline_alert(wn._(doc.status), "alert-success", "icon-ok-sign"); - } else if(doc.status=="Opportunity Lost") { - cur_frm.dashboard.set_headline_alert(wn._(doc.status), "alert-danger", "icon-exclamation-sign"); - } - } cur_frm.clear_custom_buttons(); - if(doc.docstatus === 1 && doc.status!=="Opportunity Lost") { + if(doc.docstatus === 1 && doc.status!=="Lost") { cur_frm.add_custom_button('Create Quotation', cur_frm.cscript.create_quotation); - cur_frm.add_custom_button('Opportunity Lost', cur_frm.cscript['Declare Opportunity Lost']); + if(doc.status!=="Quotation") { + cur_frm.add_custom_button('Opportunity Lost', cur_frm.cscript['Declare Opportunity Lost']); + } cur_frm.add_custom_button('Send SMS', cur_frm.cscript.send_sms); } diff --git a/selling/doctype/opportunity/opportunity.py b/selling/doctype/opportunity/opportunity.py index e0be5fa9577..e63ce6b0607 100644 --- a/selling/doctype/opportunity/opportunity.py +++ b/selling/doctype/opportunity/opportunity.py @@ -6,7 +6,7 @@ import webnotes from webnotes.utils import cstr, getdate, cint from webnotes.model.bean import getlist -from webnotes import msgprint +from webnotes import msgprint, _ from utilities.transaction_base import TransactionBase @@ -67,7 +67,8 @@ class DocType(TransactionBase): 'email_id' : contact and contact[0]['email_id'] or '' } return ret - + + def on_update(self): # Add to calendar if self.doc.contact_date and self.doc.contact_date_ref != self.doc.contact_date: @@ -120,6 +121,7 @@ class DocType(TransactionBase): msgprint("Customer is mandatory if 'Opportunity From' is selected as Customer", raise_exception=1) def validate(self): + self.set_status() self.set_last_contact_date() self.validate_item_details() self.validate_uom_is_integer("uom", "qty") @@ -127,42 +129,29 @@ class DocType(TransactionBase): from accounts.utils import validate_fiscal_year validate_fiscal_year(self.doc.transaction_date, self.doc.fiscal_year, "Opportunity Date") - self.doc.status = "Draft" def on_submit(self): - webnotes.conn.set(self.doc, 'status', 'Submitted') - if self.doc.lead and webnotes.conn.get_value("Lead", self.doc.lead, "status")!="Converted": - webnotes.conn.set_value("Lead", self.doc.lead, "status", "Opportunity Made") + if self.doc.lead: + webnotes.bean("Lead", self.doc.lead).get_controller().set_status(update=True) def on_cancel(self): - chk = webnotes.conn.sql("select t1.name from `tabQuotation` t1, `tabQuotation Item` t2 where t2.parent = t1.name and t1.docstatus=1 and (t1.status!='Order Lost' and t1.status!='Cancelled') and t2.prevdoc_docname = %s",self.doc.name) - if chk: - msgprint("Quotation No. "+cstr(chk[0][0])+" is submitted against this Opportunity. Thus can not be cancelled.") - raise Exception - else: - webnotes.conn.set(self.doc, 'status', 'Cancelled') - if self.doc.lead and webnotes.conn.get_value("Lead", self.doc.lead, - "status")!="Converted": - if webnotes.conn.get_value("Communication", {"parent": self.doc.lead}): - status = "Contacted" - else: - status = "Open" - - webnotes.conn.set_value("Lead", self.doc.lead, "status", status) + if self.has_quotation(): + webnotes.throw(_("Cannot Cancel Opportunity as Quotation Exists")) + self.set_status(update=True) def declare_enquiry_lost(self,arg): - chk = webnotes.conn.sql("select t1.name from `tabQuotation` t1, `tabQuotation Item` t2 where t2.parent = t1.name and t1.docstatus=1 and (t1.status!='Order Lost' and t1.status!='Cancelled') and t2.prevdoc_docname = %s",self.doc.name) - if chk: - msgprint("Quotation No. "+cstr(chk[0][0])+" is submitted against this Opportunity. Thus 'Opportunity Lost' can not be declared against it.") - raise Exception - else: - webnotes.conn.set(self.doc, 'status', 'Opportunity Lost') + if not self.has_quotation(): + webnotes.conn.set(self.doc, 'status', 'Lost') webnotes.conn.set(self.doc, 'order_lost_reason', arg) - return 'true' + else: + webnotes.throw(_("Cannot declare as lost, because Quotation has been made.")) def on_trash(self): self.delete_events() + def has_quotation(self): + return webnotes.conn.get_value("Quotation Item", {"prevdoc_docname": self.doc.name, "docstatus": 1}) + @webnotes.whitelist() def make_quotation(source_name, target_doclist=None): from webnotes.model.mapper import get_mapped_doclist diff --git a/selling/doctype/opportunity/opportunity.txt b/selling/doctype/opportunity/opportunity.txt index 21eae5f7234..02caea0a6d1 100644 --- a/selling/doctype/opportunity/opportunity.txt +++ b/selling/doctype/opportunity/opportunity.txt @@ -2,7 +2,7 @@ { "creation": "2013-03-07 18:50:30", "docstatus": 0, - "modified": "2013-10-02 14:24:30", + "modified": "2013-10-03 16:30:58", "modified_by": "Administrator", "owner": "Administrator" }, @@ -126,7 +126,7 @@ "no_copy": 1, "oldfieldname": "status", "oldfieldtype": "Select", - "options": "\nDraft\nSubmitted\nQuotation Sent\nOrder Confirmed\nOpportunity Lost\nCancelled", + "options": "Draft\nSubmitted\nQuotation\nLost\nCancelled\nReplied\nOpen", "read_only": 1, "reqd": 1 }, @@ -350,18 +350,6 @@ "options": "Campaign", "read_only": 0 }, - { - "depends_on": "eval:!doc.__islocal", - "doctype": "DocField", - "fieldname": "order_lost_reason", - "fieldtype": "Small Text", - "label": "Quotation Lost Reason", - "no_copy": 1, - "oldfieldname": "order_lost_reason", - "oldfieldtype": "Small Text", - "read_only": 1, - "report_hide": 0 - }, { "doctype": "DocField", "fieldname": "company", @@ -376,6 +364,15 @@ "reqd": 1, "search_index": 1 }, + { + "depends_on": "eval:!doc.__islocal", + "doctype": "DocField", + "fieldname": "order_lost_reason", + "fieldtype": "Text", + "label": "Lost Reason", + "no_copy": 1, + "read_only": 1 + }, { "doctype": "DocField", "fieldname": "column_break2", diff --git a/selling/doctype/quotation/quotation.js b/selling/doctype/quotation/quotation.js index e20308f18ee..05feed012bb 100644 --- a/selling/doctype/quotation/quotation.js +++ b/selling/doctype/quotation/quotation.js @@ -24,19 +24,10 @@ erpnext.selling.QuotationController = erpnext.selling.SellingController.extend({ }, refresh: function(doc, dt, dn) { this._super(doc, dt, dn); - - cur_frm.dashboard.reset(doc); - if(!doc.__islocal) { - if(doc.status=="Converted" || doc.status=="Order Confirmed") { - cur_frm.dashboard.set_headline_alert(wn._(doc.status), "alert-success", "icon-ok-sign"); - } else if(doc.status==="Order Lost") { - cur_frm.dashboard.set_headline_alert(wn._(doc.status), "alert-danger", "icon-exclamation-sign"); - } - } - if(doc.docstatus == 1 && doc.status!=='Order Lost') { + if(doc.docstatus == 1 && doc.status!=='Lost') { cur_frm.add_custom_button('Make Sales Order', cur_frm.cscript['Make Sales Order']); - if(doc.status!=="Order Confirmed") { + if(doc.status!=="Ordered") { cur_frm.add_custom_button('Set as Lost', cur_frm.cscript['Declare Order Lost']); } cur_frm.add_custom_button('Send SMS', cur_frm.cscript.send_sms); diff --git a/selling/doctype/quotation/quotation.py b/selling/doctype/quotation/quotation.py index 8a3bef10e9f..697f805a2c0 100644 --- a/selling/doctype/quotation/quotation.py +++ b/selling/doctype/quotation/quotation.py @@ -47,6 +47,11 @@ class DocType(SellingController): if not doc.fields.get(r): doc.fields[r] = res[r] + + def has_sales_order(self): + return webnotes.conn.get_value("Sales Order Item", {"prevdoc_docname": self.doc.name, "docstatus": 1}) + + # Re-calculates Basic Rate & amount based on Price List Selected # -------------------------------------------------------------- def get_adj_percent(self, arg=''): @@ -108,13 +113,7 @@ class DocType(SellingController): def validate(self): super(DocType, self).validate() - import utilities - if not self.doc.status: - self.doc.status = "Draft" - else: - utilities.validate_status(self.doc.status, ["Draft", "Submitted", - "Order Confirmed", "Order Lost", "Cancelled"]) - + self.set_status() self.set_last_contact_date() self.validate_order_type() self.validate_for_items() @@ -125,42 +124,22 @@ class DocType(SellingController): sales_com_obj.check_active_sales_items(self) sales_com_obj.validate_max_discount(self,'quotation_details') sales_com_obj.check_conversion_rate(self) - - - def on_update(self): - # Set Quotation Status - webnotes.conn.set(self.doc, 'status', 'Draft') - + #update enquiry #------------------ - def update_enquiry(self, flag): - prevdoc='' - for d in getlist(self.doclist, 'quotation_details'): - if d.prevdoc_docname: - prevdoc = d.prevdoc_docname - - if prevdoc: - if flag == 'submit': #on submit - webnotes.conn.sql("update `tabOpportunity` set status = 'Quotation Sent' where name = %s", prevdoc) - elif flag == 'cancel': #on cancel - webnotes.conn.sql("update `tabOpportunity` set status = 'Open' where name = %s", prevdoc) - elif flag == 'order lost': #order lost - webnotes.conn.sql("update `tabOpportunity` set status = 'Opportunity Lost' where name=%s", prevdoc) - elif flag == 'order confirm': #order confirm - webnotes.conn.sql("update `tabOpportunity` set status='Order Confirmed' where name=%s", prevdoc) + def update_opportunity(self): + for opportunity in self.doclist.get_distinct_values("prevdoc_docname"): + webnotes.bean("Opportunity", opportunity).get_controller().set_status(update=True) # declare as order lost #------------------------- def declare_order_lost(self, arg): - chk = webnotes.conn.sql("select t1.name from `tabSales Order` t1, `tabSales Order Item` t2 where t2.parent = t1.name and t1.docstatus=1 and t2.prevdoc_docname = %s",self.doc.name) - if chk: - msgprint("Sales Order No. "+cstr(chk[0][0])+" is submitted against this Quotation. Thus 'Order Lost' can not be declared against it.") - raise Exception - else: - webnotes.conn.set(self.doc, 'status', 'Order Lost') + if not self.has_sales_order(): + webnotes.conn.set(self.doc, 'status', 'Lost') webnotes.conn.set(self.doc, 'order_lost_reason', arg) - self.update_enquiry('order lost') - return 'true' + self.update_opportunity() + else: + webnotes.throw(_("Cannot set as Lost as Sales Order is made.")) #check if value entered in item table #-------------------------------------- @@ -176,21 +155,17 @@ class DocType(SellingController): # Check for Approving Authority get_obj('Authorization Control').validate_approving_authority(self.doc.doctype, self.doc.company, self.doc.grand_total, self) - - # Set Quotation Status - webnotes.conn.set(self.doc, 'status', 'Submitted') - + #update enquiry status - self.update_enquiry('submit') + self.update_opportunity() # ON CANCEL # ========================================================================== def on_cancel(self): #update enquiry status - self.update_enquiry('cancel') - - webnotes.conn.set(self.doc,'status','Cancelled') + self.set_status() + self.update_opportunity() # Print other charges # =========================================================================== @@ -202,6 +177,7 @@ class DocType(SellingController): lst1.append(d.total) print_lst.append(lst1) return print_lst + @webnotes.whitelist() def make_sales_order(source_name, target_doclist=None): diff --git a/selling/doctype/quotation/quotation.txt b/selling/doctype/quotation/quotation.txt index 200627f794f..8a8b24ba44b 100644 --- a/selling/doctype/quotation/quotation.txt +++ b/selling/doctype/quotation/quotation.txt @@ -2,7 +2,7 @@ { "creation": "2013-05-24 19:29:08", "docstatus": 0, - "modified": "2013-10-02 14:24:35", + "modified": "2013-10-03 16:31:55", "modified_by": "Administrator", "owner": "Administrator" }, @@ -734,7 +734,7 @@ "no_copy": 1, "oldfieldname": "status", "oldfieldtype": "Select", - "options": "\nDraft\nSubmitted\nOrder Confirmed\nOrder Lost\nCancelled", + "options": "Draft\nSubmitted\nOrdered\nLost\nCancelled", "print_hide": 1, "read_only": 1, "reqd": 1, diff --git a/selling/doctype/sales_order/sales_order.js b/selling/doctype/sales_order/sales_order.js index 0c261793e15..bf23b9cb9df 100644 --- a/selling/doctype/sales_order/sales_order.js +++ b/selling/doctype/sales_order/sales_order.js @@ -66,7 +66,7 @@ erpnext.selling.SalesOrderController = erpnext.selling.SellingController.extend( source_doctype: "Quotation", get_query_filters: { docstatus: 1, - status: ["!=", "Order Lost"], + status: ["!=", "Lost"], order_type: cur_frm.doc.order_type, customer: cur_frm.doc.customer || undefined, company: cur_frm.doc.company diff --git a/selling/doctype/sales_order/sales_order.py b/selling/doctype/sales_order/sales_order.py index 8fc728fccdc..d3ac7ad339d 100644 --- a/selling/doctype/sales_order/sales_order.py +++ b/selling/doctype/sales_order/sales_order.py @@ -165,36 +165,20 @@ class DocType(SellingController): }) - def check_prev_docstatus(self): - for d in getlist(self.doclist, 'sales_order_details'): - cancel_quo = webnotes.conn.sql("select name from `tabQuotation` where docstatus = 2 and name = '%s'" % d.prevdoc_docname) - if cancel_quo: - msgprint("Quotation :" + cstr(cancel_quo[0][0]) + " is already cancelled !") - raise Exception , "Validation Error. " - def update_enquiry_status(self, prevdoc, flag): enq = webnotes.conn.sql("select t2.prevdoc_docname from `tabQuotation` t1, `tabQuotation Item` t2 where t2.parent = t1.name and t1.name=%s", prevdoc) if enq: webnotes.conn.sql("update `tabOpportunity` set status = %s where name=%s",(flag,enq[0][0])) - def update_prevdoc_status(self, flag): - for d in getlist(self.doclist, 'sales_order_details'): - if d.prevdoc_docname: - if flag=='submit': - webnotes.conn.sql("update `tabQuotation` set status = 'Order Confirmed' where name=%s",d.prevdoc_docname) - - #update enquiry - self.update_enquiry_status(d.prevdoc_docname, 'Order Confirmed') - elif flag == 'cancel': - chk = webnotes.conn.sql("select t1.name from `tabSales Order` t1, `tabSales Order Item` t2 where t2.parent = t1.name and t2.prevdoc_docname=%s and t1.name!=%s and t1.docstatus=1", (d.prevdoc_docname,self.doc.name)) - if not chk: - webnotes.conn.sql("update `tabQuotation` set status = 'Submitted' where name=%s",d.prevdoc_docname) - - #update enquiry - self.update_enquiry_status(d.prevdoc_docname, 'Quotation Sent') + def update_prevdoc_status(self, flag): + for quotation in self.doclist.get_distinct_values("prevdoc_docname"): + bean = webnotes.bean("Quotation", quotation) + if bean.doc.docstatus==2: + webnotes.throw(d.prevdoc_docname + ": " + webnotes._("Quotation is cancelled.")) + + bean.get_controller().set_status(update=True) def on_submit(self): - self.check_prev_docstatus() self.update_stock_ledger(update_stock = 1) get_obj('Sales Common').check_credit(self,self.doc.grand_total) diff --git a/support/doctype/support_ticket/get_support_mails.py b/support/doctype/support_ticket/get_support_mails.py index 4dcb59e4fe6..4b61352faef 100644 --- a/support/doctype/support_ticket/get_support_mails.py +++ b/support/doctype/support_ticket/get_support_mails.py @@ -54,7 +54,7 @@ Original Query: def auto_close_tickets(self): webnotes.conn.sql("""update `tabSupport Ticket` set status = 'Closed' - where status = 'Waiting for Customer' + where status = 'Replied' and date_sub(curdate(),interval 15 Day) > modified""") def get_support_mails(): diff --git a/support/doctype/support_ticket/support_ticket.py b/support/doctype/support_ticket/support_ticket.py index bf2a9fbabed..eb68ff3bea8 100644 --- a/support/doctype/support_ticket/support_ticket.py +++ b/support/doctype/support_ticket/support_ticket.py @@ -14,7 +14,7 @@ class DocType(TransactionBase): def get_sender(self, comm): return webnotes.conn.get_value('Email Settings',None,'support_email') - + def get_subject(self, comm): return '[' + self.doc.name + '] ' + (comm.subject or 'No Subject Specified') @@ -35,16 +35,7 @@ class DocType(TransactionBase): if self.doc.status == "Closed": from webnotes.widgets.form.assign_to import clear clear(self.doc.doctype, self.doc.name) - - def on_communication(self, comm): - if comm.sender == self.get_sender(comm) or \ - webnotes.conn.get_value("Profile", extract_email_id(comm.sender), "user_type")=="System User": - self.doc.status = "Waiting for Customer" - else: - self.doc.status = "Open" - self.update_status() - self.doc.save() - + def set_lead_contact(self, email_id): import email.utils email_id = email.utils.parseaddr(email_id) diff --git a/support/doctype/support_ticket/support_ticket.txt b/support/doctype/support_ticket/support_ticket.txt index 9f385b2d25b..76d9dcfb1e9 100644 --- a/support/doctype/support_ticket/support_ticket.txt +++ b/support/doctype/support_ticket/support_ticket.txt @@ -2,7 +2,7 @@ { "creation": "2013-02-01 10:36:25", "docstatus": 0, - "modified": "2013-09-10 10:54:02", + "modified": "2013-10-03 16:45:41", "modified_by": "Administrator", "owner": "Administrator" }, @@ -71,7 +71,7 @@ "no_copy": 1, "oldfieldname": "status", "oldfieldtype": "Select", - "options": "\nOpen\nTo Reply\nWaiting for Customer\nHold\nClosed", + "options": "Open\nReplied\nHold\nClosed", "read_only": 0, "reqd": 0, "search_index": 1 diff --git a/utilities/doctype/contact/contact.py b/utilities/doctype/contact/contact.py index 58437f1a62d..db233fb68de 100644 --- a/utilities/doctype/contact/contact.py +++ b/utilities/doctype/contact/contact.py @@ -12,14 +12,6 @@ class DocType(TransactionBase): self.doc = doc self.doclist = doclist - def on_communication(self, comm): - if webnotes.conn.get_value("Profile", extract_email_id(comm.sender), "user_type")=="System User": - status = "Replied" - else: - status = "Open" - - webnotes.conn.set(self.doc, 'status', status) - def autoname(self): # concat first and last name self.doc.name = " ".join(filter(None, @@ -32,6 +24,7 @@ class DocType(TransactionBase): break def validate(self): + self.set_status() self.validate_primary_contact() def validate_primary_contact(self): diff --git a/utilities/doctype/contact/contact.txt b/utilities/doctype/contact/contact.txt index 92dcf2ef023..db23410820f 100644 --- a/utilities/doctype/contact/contact.txt +++ b/utilities/doctype/contact/contact.txt @@ -2,7 +2,7 @@ { "creation": "2013-01-10 16:34:32", "docstatus": 0, - "modified": "2013-09-10 10:50:27", + "modified": "2013-10-03 16:44:08", "modified_by": "Administrator", "owner": "Administrator" }, @@ -70,11 +70,12 @@ "fieldtype": "Column Break" }, { + "default": "Passive", "doctype": "DocField", "fieldname": "status", "fieldtype": "Select", "label": "Status", - "options": "\nOpen\nReplied" + "options": "Passive\nOpen\nReplied" }, { "doctype": "DocField", From 6856d74a1bc463e682ecc178f213d82acb0e7ac6 Mon Sep 17 00:00:00 2001 From: Rushabh Mehta Date: Thu, 3 Oct 2013 18:12:36 +0530 Subject: [PATCH 074/200] [minor] fixes to crm patch --- controllers/status_updater.py | 16 +++++++++------- .../p01_update_delivery_note_prevdocs.py | 1 + patches/october_2013/p03_crm_update_status.py | 17 ++++++++++++++++- 3 files changed, 26 insertions(+), 8 deletions(-) diff --git a/controllers/status_updater.py b/controllers/status_updater.py index 07b812a7dc1..e457fa957ef 100644 --- a/controllers/status_updater.py +++ b/controllers/status_updater.py @@ -69,12 +69,14 @@ class StatusUpdater(DocListController): if self.doc.get("__islocal"): return - if self.doc.doctype in status_map.keys(): - for s in status_map[self.doc.doctype].reverse(): + if self.doc.doctype in status_map: + sl = status_map[self.doc.doctype][:] + sl.reverse() + for s in sl: if not s[1]: self.doc.status = s[0] break - elif s[1].startwith("eval:"): + elif s[1].startswith("eval:"): if eval(s[1][5:]): self.doc.status = s[0] break @@ -89,14 +91,14 @@ class StatusUpdater(DocListController): self.set_status(update=True) def communication_received(self): - last_comm = self.doclist.get({"doctype":"Communication"})[-1] + last_comm = self.doclist.get({"doctype":"Communication"}) if last_comm: - return last_comm.sent_or_received == "Received" + return last_comm[-1].sent_or_received == "Received" def communication_sent(self): - last_comm = self.doclist.get({"doctype":"Communication"})[-1] + last_comm = self.doclist.get({"doctype":"Communication"}) if last_comm: - return last_comm.sent_or_received == "Sent" + return last_comm[-1].sent_or_received == "Sent" def validate_qty(self): """ diff --git a/patches/october_2013/p01_update_delivery_note_prevdocs.py b/patches/october_2013/p01_update_delivery_note_prevdocs.py index b1a16c28beb..75ac53f9837 100644 --- a/patches/october_2013/p01_update_delivery_note_prevdocs.py +++ b/patches/october_2013/p01_update_delivery_note_prevdocs.py @@ -5,6 +5,7 @@ from __future__ import unicode_literals import webnotes def execute(): + webnotes.reload_doc("stock", "doctype", "delivery_note_item") webnotes.conn.sql("""update `tabDelivery Note Item` set against_sales_order=prevdoc_docname where prevdoc_doctype='Sales Order' """) diff --git a/patches/october_2013/p03_crm_update_status.py b/patches/october_2013/p03_crm_update_status.py index e5b434ce1ff..73ed1b1c78c 100644 --- a/patches/october_2013/p03_crm_update_status.py +++ b/patches/october_2013/p03_crm_update_status.py @@ -29,4 +29,19 @@ def execute(): ["Waiting for Customer", "Replied"], ["To Reply", "Open"], ] - } \ No newline at end of file + } + + for dt, opts in change_map.items(): + for status in opts: + webnotes.conn.sql("""update `tab%s` set status=%s where status=%s""" % \ + (dt, "%s", "%s"), (status[1], status[0])) + + # for dt in ["Lead", "Opportunity"]: + # for name in webnotes.conn.sql_list("""select name from `tab%s`""" % dt): + # bean = webnotes.bean(dt, name) + # before_status = bean.doc.status + # bean.get_controller().set_status() + # + # if bean.doc.status != before_status: + # webnotes.conn.sql("""update `tab%s` set status=%s where name=%s""" % (dt, "%s", "%s"), + # (bean.doc.status, name)) From 3ab6a6574337541fd03b22bf67d9ab36d3a484e0 Mon Sep 17 00:00:00 2001 From: Anand Doshi Date: Thu, 3 Oct 2013 19:32:23 +0530 Subject: [PATCH 075/200] [minor] [fix] communication status patch --- patches/october_2013/p02_set_communication_status.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/patches/october_2013/p02_set_communication_status.py b/patches/october_2013/p02_set_communication_status.py index 8360fe6ceeb..d67d08dbe0a 100644 --- a/patches/october_2013/p02_set_communication_status.py +++ b/patches/october_2013/p02_set_communication_status.py @@ -5,5 +5,7 @@ from __future__ import unicode_literals import webnotes def execute(): + webnotes.reload_doc("core", "doctype", "communication") + webnotes.conn.sql("""update tabCommunication set sent_or_received= if(ifnull(recipients, '')='', "Received", "Sent")""") \ No newline at end of file From cf0f3a02d45bd346e4154f300276bf841d630ed6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A1rbara=20Perretti?= Date: Thu, 3 Oct 2013 13:58:56 -0300 Subject: [PATCH 076/200] Fix translate item.js --- stock/doctype/item/item.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/stock/doctype/item/item.js b/stock/doctype/item/item.js index a83032e8f26..9d470954e77 100644 --- a/stock/doctype/item/item.js +++ b/stock/doctype/item/item.js @@ -116,7 +116,7 @@ cur_frm.fields_dict['item_group'].get_query = function(doc,cdt,cdn) { // in the "alternate_description" field cur_frm.cscript.add_image = function(doc, dt, dn) { if(!doc.image) { - msgprint('Please select an "Image" first'); + msgprint(wn._('Please select an "Image" first')); return; } @@ -132,7 +132,7 @@ cur_frm.cscript.weight_to_validate = function(doc,cdt,cdn){ if((doc.nett_weight || doc.gross_weight) && !doc.weight_uom) { - alert('Weight is mentioned,\nPlease mention "Weight UOM" too'); + alert(wn._('Weight is mentioned,\nPlease mention "Weight UOM" too')); validated=0; } } From eb331c225e4d03e52dff7f56db4e72a8036e133b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A1rbara=20Perretti?= Date: Thu, 3 Oct 2013 14:03:07 -0300 Subject: [PATCH 077/200] Fix translate material_request.js --- .../material_request/material_request.js | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/stock/doctype/material_request/material_request.js b/stock/doctype/material_request/material_request.js index 6931181dbac..61be6369da9 100644 --- a/stock/doctype/material_request/material_request.js +++ b/stock/doctype/material_request/material_request.js @@ -23,21 +23,21 @@ erpnext.buying.MaterialRequestController = erpnext.buying.BuyingController.exten if(doc.docstatus == 1 && doc.status != 'Stopped'){ if(doc.material_request_type === "Purchase") - cur_frm.add_custom_button("Make Supplier Quotation", + cur_frm.add_custom_button(wn._("Make Supplier Quotation"), this.make_supplier_quotation); if(doc.material_request_type === "Transfer" && doc.status === "Submitted") - cur_frm.add_custom_button("Transfer Material", this.make_stock_entry); + cur_frm.add_custom_button(wn._("Transfer Material"), this.make_stock_entry); if(flt(doc.per_ordered, 2) < 100) { if(doc.material_request_type === "Purchase") - cur_frm.add_custom_button('Make Purchase Order', + cur_frm.add_custom_button(wn._('Make Purchase Order'), this.make_purchase_order); - cur_frm.add_custom_button('Stop Material Request', + cur_frm.add_custom_button(wn._('Stop Material Request'), cur_frm.cscript['Stop Material Request']); } - cur_frm.add_custom_button('Send SMS', cur_frm.cscript.send_sms); + cur_frm.add_custom_button(wn._('Send SMS'), cur_frm.cscript.send_sms); } @@ -58,7 +58,7 @@ erpnext.buying.MaterialRequestController = erpnext.buying.BuyingController.exten } if(doc.docstatus == 1 && doc.status == 'Stopped') - cur_frm.add_custom_button('Unstop Material Request', + cur_frm.add_custom_button(wn._('Unstop Material Request'), cur_frm.cscript['Unstop Material Request']); }, @@ -103,12 +103,12 @@ $.extend(cur_frm.cscript, new erpnext.buying.MaterialRequestController({frm: cur cur_frm.cscript.qty = function(doc, cdt, cdn) { var d = locals[cdt][cdn]; if (flt(d.qty) < flt(d.min_order_qty)) - alert("Warning: Material Requested Qty is less than Minimum Order Qty"); + alert(wn._("Warning: Material Requested Qty is less than Minimum Order Qty")); }; cur_frm.cscript['Stop Material Request'] = function() { var doc = cur_frm.doc; - var check = confirm("Do you really want to STOP this Material Request?"); + var check = confirm(wn._("Do you really want to STOP this Material Request?")); if (check) { return $c('runserverobj', args={'method':'update_status', 'arg': 'Stopped', 'docs': wn.model.compress(make_doclist(doc.doctype, doc.name))}, function(r,rt) { @@ -119,7 +119,7 @@ cur_frm.cscript['Stop Material Request'] = function() { cur_frm.cscript['Unstop Material Request'] = function(){ var doc = cur_frm.doc; - var check = confirm("Do you really want to UNSTOP this Material Request?"); + var check = confirm(wn._("Do you really want to UNSTOP this Material Request?")); if (check) { return $c('runserverobj', args={'method':'update_status', 'arg': 'Submitted','docs': wn.model.compress(make_doclist(doc.doctype, doc.name))}, function(r,rt) { From 1395dafb12db4080f18107a45880e617a0b95d3c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A1rbara=20Perretti?= Date: Thu, 3 Oct 2013 14:12:43 -0300 Subject: [PATCH 078/200] Fix translate packing_slip.js --- stock/doctype/packing_slip/packing_slip.js | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/stock/doctype/packing_slip/packing_slip.js b/stock/doctype/packing_slip/packing_slip.js index eba20c5579e..f0a0ba57fc5 100644 --- a/stock/doctype/packing_slip/packing_slip.js +++ b/stock/doctype/packing_slip/packing_slip.js @@ -45,13 +45,13 @@ cur_frm.cscript.validate = function(doc, cdt, cdn) { cur_frm.cscript.validate_case_nos = function(doc) { doc = locals[doc.doctype][doc.name]; if(cint(doc.from_case_no)==0) { - msgprint("Case No. cannot be 0") + msgprint(wn._("Case No. cannot be 0")) validated = false; } else if(!cint(doc.to_case_no)) { doc.to_case_no = doc.from_case_no; refresh_field('to_case_no'); } else if(cint(doc.to_case_no) < cint(doc.from_case_no)) { - msgprint("'To Case No.' cannot be less than 'From Case No.'"); + msgprint(wn._("'To Case No.' cannot be less than 'From Case No.'")); validated = false; } } @@ -72,14 +72,14 @@ cur_frm.cscript.validate_duplicate_items = function(doc, ps_detail) { for(var i=0; i Date: Thu, 3 Oct 2013 14:18:12 -0300 Subject: [PATCH 079/200] Fix translate purchase_receipt.js --- stock/doctype/purchase_receipt/purchase_receipt.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/stock/doctype/purchase_receipt/purchase_receipt.js b/stock/doctype/purchase_receipt/purchase_receipt.js index 8775140a8bd..24389260cae 100644 --- a/stock/doctype/purchase_receipt/purchase_receipt.js +++ b/stock/doctype/purchase_receipt/purchase_receipt.js @@ -16,15 +16,15 @@ erpnext.stock.PurchaseReceiptController = erpnext.buying.BuyingController.extend if(this.frm.doc.docstatus == 1) { if(!this.frm.doc.__billing_complete) { - cur_frm.add_custom_button('Make Purchase Invoice', + cur_frm.add_custom_button(wn._('Make Purchase Invoice'), this.make_purchase_invoice); } - cur_frm.add_custom_button('Send SMS', cur_frm.cscript['Send SMS']); + cur_frm.add_custom_button(wn._('Send SMS'), cur_frm.cscript['Send SMS']); this.show_stock_ledger(); this.show_general_ledger(); } else { - cur_frm.add_custom_button(wn._('From Purchase Order'), + cur_frm.add_custom_button(wn._(wn._('From Purchase Order')), function() { wn.model.map_current_doc({ method: "buying.doctype.purchase_order.purchase_order.make_purchase_receipt", @@ -139,7 +139,7 @@ cur_frm.fields_dict['purchase_receipt_details'].grid.get_field('batch_no').get_q } } else{ - alert("Please enter Item Code."); + alert(wn._("Please enter Item Code.")); } } From 995994f7c44368a16e9f496c301b2644e9f9a160 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A1rbara=20Perretti?= Date: Thu, 3 Oct 2013 14:57:34 -0300 Subject: [PATCH 080/200] fix translate stock_entry.js --- stock/doctype/stock_entry/stock_entry.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/stock/doctype/stock_entry/stock_entry.js b/stock/doctype/stock_entry/stock_entry.js index 4695fdb22c2..e451f8972cc 100644 --- a/stock/doctype/stock_entry/stock_entry.js +++ b/stock/doctype/stock_entry/stock_entry.js @@ -67,10 +67,10 @@ erpnext.stock.StockEntry = erpnext.stock.StockController.extend({ if(this.frm.doc.docstatus === 1 && wn.boot.profile.can_create.indexOf("Journal Voucher")!==-1) { 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(wn._("Make Credit Note"), function() { me.make_return_jv(); }); this.add_excise_button(); } else if(this.frm.doc.purpose === "Purchase Return") { - this.frm.add_custom_button("Make Debit Note", function() { me.make_return_jv(); }); + this.frm.add_custom_button(wn._("Make Debit Note"), function() { me.make_return_jv(); }); this.add_excise_button(); } } @@ -191,7 +191,7 @@ erpnext.stock.StockEntry = erpnext.stock.StockController.extend({ add_excise_button: function() { if(wn.boot.control_panel.country === "India") - this.frm.add_custom_button("Make Excise Invoice", function() { + this.frm.add_custom_button(wn._("Make Excise Invoice"), function() { var excise = wn.model.make_new_doc_and_get_name('Journal Voucher'); excise = locals['Journal Voucher'][excise]; excise.voucher_type = 'Excise Voucher'; @@ -307,7 +307,7 @@ cur_frm.fields_dict['mtn_details'].grid.get_field('batch_no').get_query = functi } } } else { - msgprint("Please enter Item Code to get batch no"); + msgprint(wn._("Please enter Item Code to get batch no")); } } @@ -356,7 +356,7 @@ cur_frm.cscript.validate = function(doc, cdt, cdn) { cur_frm.cscript.validate_items = function(doc) { cl = getchildren('Stock Entry Detail',doc.name,'mtn_details'); if (!cl.length) { - alert("Item table can not be blank"); + alert(wn._("Item table can not be blank")); validated = false; } } From 8252f2a34f334db3fd416bccd839a99f21ddc86c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A1rbara=20Perretti?= Date: Thu, 3 Oct 2013 15:15:01 -0300 Subject: [PATCH 081/200] Fix translate stock_reconciliation.js --- .../stock_reconciliation.js | 36 +++++++++---------- 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/stock/doctype/stock_reconciliation/stock_reconciliation.js b/stock/doctype/stock_reconciliation/stock_reconciliation.js index 7373648972b..481a0038edb 100644 --- a/stock/doctype/stock_reconciliation/stock_reconciliation.js +++ b/stock/doctype/stock_reconciliation/stock_reconciliation.js @@ -48,13 +48,13 @@ erpnext.stock.StockReconciliation = erpnext.stock.StockController.extend({ this.show_download_template(); this.show_upload(); if(this.frm.doc.reconciliation_json) { - this.frm.set_intro("You can submit this Stock Reconciliation."); + this.frm.set_intro(wn._("You can submit this Stock Reconciliation.")); } else { - this.frm.set_intro("Download the Template, fill appropriate data and \ - attach the modified file."); + this.frm.set_intro(wn._("Download the Template, fill appropriate data and \ + attach the modified file.")); } } else if(this.frm.doc.docstatus == 1) { - this.frm.set_intro("Cancelling this Stock Reconciliation will nullify its effect."); + this.frm.set_intro(wn._("Cancelling this Stock Reconciliation will nullify its effect.")); this.show_stock_ledger(); this.show_general_ledger(); } else { @@ -66,20 +66,20 @@ erpnext.stock.StockReconciliation = erpnext.stock.StockController.extend({ show_download_template: function() { var me = this; - this.frm.add_custom_button("Download Template", function() { - this.title = "Stock Reconcilation Template"; - wn.tools.downloadify([["Stock Reconciliation"], + this.frm.add_custom_button(wn._("Download Template"), function() { + this.title = wn._("Stock Reconcilation Template"); + wn.tools.downloadify([[wn._("Stock Reconciliation")], ["----"], - ["Stock Reconciliation can be used to update the stock on a particular date," - + " usually as per physical inventory."], - ["When submitted, the system creates difference entries" - + " to set the given stock and valuation on this date."], - ["It can also be used to create opening stock entries and to fix stock value."], + [wn._("Stock Reconciliation can be used to update the stock on a particular date, ") + + wn._("usually as per physical inventory.")], + [wn._("When submitted, the system creates difference entries ") + + wn._("to set the given stock and valuation on this date.")], + [wn._("It can also be used to create opening stock entries and to fix stock value.")], ["----"], - ["Notes:"], - ["Item Code and Warehouse should already exist."], - ["You can update either Quantity or Valuation Rate or both."], - ["If no change in either Quantity or Valuation Rate, leave the cell blank."], + [wn._("Notes:")], + [wn._("Item Code and Warehouse should already exist.")], + [wn._("You can update either Quantity or Valuation Rate or both.")], + [wn._("If no change in either Quantity or Valuation Rate, leave the cell blank.")], ["----"], ["Item Code", "Warehouse", "Quantity", "Valuation Rate"]], null, this); return false; @@ -113,8 +113,8 @@ erpnext.stock.StockReconciliation = erpnext.stock.StockController.extend({ show_download_reconciliation_data: function() { var me = this; if(this.frm.doc.reconciliation_json) { - this.frm.add_custom_button("Download Reconcilation Data", function() { - this.title = "Stock Reconcilation Data"; + this.frm.add_custom_button(wn._("Download Reconcilation Data"), function() { + this.title = wn._("Stock Reconcilation Data"); wn.tools.downloadify(JSON.parse(me.frm.doc.reconciliation_json), null, this); return false; }, "icon-download"); From dfe053fccd23e19de3ea7ce57a288f2b7dcceb2b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A1rbara=20Perretti?= Date: Thu, 3 Oct 2013 15:26:36 -0300 Subject: [PATCH 082/200] Fix translate warehouse.js --- stock/doctype/warehouse/warehouse.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/stock/doctype/warehouse/warehouse.js b/stock/doctype/warehouse/warehouse.js index 2a58a387f88..c33f09a9a23 100644 --- a/stock/doctype/warehouse/warehouse.js +++ b/stock/doctype/warehouse/warehouse.js @@ -7,11 +7,11 @@ cur_frm.cscript.refresh = function(doc) { cur_frm.cscript.merge = function(doc, cdt, cdn) { if (!doc.merge_with) { - msgprint("Please enter the warehouse to which you want to merge?"); + msgprint(wn._("Please enter the warehouse to which you want to merge?")); return; } - var check = confirm("Are you sure you want to merge this warehouse into " - + doc.merge_with + "?"); + var check = confirm(wn._("Are you sure you want to merge this warehouse into " + + doc.merge_with + "?")); if (check) { return $c_obj(make_doclist(cdt, cdn), 'merge_warehouses', '', ''); } From 0cd1bcf44f8c9c8ed46f4d02829738f812d91ad0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A1rbara=20Perretti?= Date: Thu, 3 Oct 2013 15:32:35 -0300 Subject: [PATCH 083/200] Fix translate stock_ageing.js --- stock/page/stock_ageing/stock_ageing.js | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/stock/page/stock_ageing/stock_ageing.js b/stock/page/stock_ageing/stock_ageing.js index 920ac848d05..98f7ace40f3 100644 --- a/stock/page/stock_ageing/stock_ageing.js +++ b/stock/page/stock_ageing/stock_ageing.js @@ -5,7 +5,7 @@ wn.pages['stock-ageing'].onload = function(wrapper) { wn.ui.make_app_page({ parent: wrapper, - title: 'Stock Ageing', + title: wn._('Stock Ageing'), single_column: true }); @@ -21,7 +21,7 @@ wn.require("app/js/stock_grid_report.js"); erpnext.StockAgeing = erpnext.StockGridReport.extend({ init: function(wrapper) { this._super({ - title: "Stock Ageing", + title: wn._("Stock Ageing"), page: wrapper, parent: $(wrapper).find('.layout-main'), appframe: wrapper.appframe, @@ -50,17 +50,17 @@ erpnext.StockAgeing = erpnext.StockGridReport.extend({ ]; }, filters: [ - {fieldtype:"Select", label: "Warehouse", link:"Warehouse", + {fieldtype:"Select", label: wn._("Warehouse"), link:"Warehouse", default_value: "Select Warehouse..."}, - {fieldtype:"Select", label: "Brand", link:"Brand", + {fieldtype:"Select", label: wn._("Brand"), link:"Brand", default_value: "Select Brand...", filter: function(val, item, opts) { return val == opts.default_value || item.brand == val; }, link_formatter: {filter_input: "brand"}}, - {fieldtype:"Select", label: "Plot By", + {fieldtype:"Select", label: wn._("Plot By"), options: ["Average Age", "Earliest", "Latest"]}, - {fieldtype:"Date", label: "To Date"}, - {fieldtype:"Button", label: "Refresh", icon:"icon-refresh icon-white", cssClass:"btn-info"}, - {fieldtype:"Button", label: "Reset Filters"} + {fieldtype:"Date", label: wn._("To Date")}, + {fieldtype:"Button", label: wn._("Refresh"), icon:"icon-refresh icon-white", cssClass:"btn-info"}, + {fieldtype:"Button", label: wn._("Reset Filters")} ], setup_filters: function() { var me = this; From 18f91ea7de051b1396258386a6dbd5efb6b6a219 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A1rbara=20Perretti?= Date: Thu, 3 Oct 2013 15:41:49 -0300 Subject: [PATCH 084/200] fix translate stock_analytics.js --- stock/page/stock_analytics/stock_analytics.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stock/page/stock_analytics/stock_analytics.js b/stock/page/stock_analytics/stock_analytics.js index 547f5ac844a..d5aa219cde7 100644 --- a/stock/page/stock_analytics/stock_analytics.js +++ b/stock/page/stock_analytics/stock_analytics.js @@ -5,7 +5,7 @@ wn.pages['stock-analytics'].onload = function(wrapper) { wn.ui.make_app_page({ parent: wrapper, - title: 'Stock Analytics', + title: wn._('Stock Analytics'), single_column: true }); From ebb8dcf6f0262d2a9a027cad9190629ccf9a3446 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A1rbara=20Perretti?= Date: Thu, 3 Oct 2013 16:03:59 -0300 Subject: [PATCH 085/200] fix translate stock_balance.js --- stock/page/stock_balance/stock_balance.js | 46 +++++++++++------------ 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/stock/page/stock_balance/stock_balance.js b/stock/page/stock_balance/stock_balance.js index 1bc5d1c6bc0..9ccc028cc83 100644 --- a/stock/page/stock_balance/stock_balance.js +++ b/stock/page/stock_balance/stock_balance.js @@ -6,7 +6,7 @@ wn.require("app/js/stock_analytics.js"); wn.pages['stock-balance'].onload = function(wrapper) { wn.ui.make_app_page({ parent: wrapper, - title: 'Stock Balance', + title: wn._('Stock Balance'), single_column: true }); @@ -20,58 +20,58 @@ wn.pages['stock-balance'].onload = function(wrapper) { erpnext.StockBalance = erpnext.StockAnalytics.extend({ init: function(wrapper) { this._super(wrapper, { - title: "Stock Balance", + title: wn._("Stock Balance"), doctypes: ["Item", "Item Group", "Warehouse", "Stock Ledger Entry", "Brand", "Stock Entry", "Project"], }); }, setup_columns: function() { this.columns = [ - {id: "name", name: "Item", field: "name", width: 300, + {id: "name", name: wn._("Item"), field: "name", width: 300, formatter: this.tree_formatter}, - {id: "item_name", name: "Item Name", field: "item_name", width: 100}, - {id: "description", name: "Description", field: "description", width: 200, + {id: "item_name", name: wn._("Item Name"), field: "item_name", width: 100}, + {id: "description", name: wn._("Description"), field: "description", width: 200, formatter: this.text_formatter}, - {id: "brand", name: "Brand", field: "brand", width: 100}, - {id: "stock_uom", name: "UOM", field: "stock_uom", width: 100}, - {id: "opening_qty", name: "Opening Qty", field: "opening_qty", width: 100, + {id: "brand", name: wn._("Brand"), field: "brand", width: 100}, + {id: "stock_uom", name: wn._("UOM"), field: "stock_uom", width: 100}, + {id: "opening_qty", name: wn._("Opening Qty"), field: "opening_qty", width: 100, formatter: this.currency_formatter}, - {id: "inflow_qty", name: "In Qty", field: "inflow_qty", width: 100, + {id: "inflow_qty", name: wn._("In Qty"), field: "inflow_qty", width: 100, formatter: this.currency_formatter}, - {id: "outflow_qty", name: "Out Qty", field: "outflow_qty", width: 100, + {id: "outflow_qty", name: wn._("Out Qty"), field: "outflow_qty", width: 100, formatter: this.currency_formatter}, - {id: "closing_qty", name: "Closing Qty", field: "closing_qty", width: 100, + {id: "closing_qty", name: wn._("Closing Qty"), field: "closing_qty", width: 100, formatter: this.currency_formatter}, - {id: "opening_value", name: "Opening Value", field: "opening_value", width: 100, + {id: "opening_value", name: wn._("Opening Value"), field: "opening_value", width: 100, formatter: this.currency_formatter}, - {id: "inflow_value", name: "In Value", field: "inflow_value", width: 100, + {id: "inflow_value", name: wn._("In Value"), field: "inflow_value", width: 100, formatter: this.currency_formatter}, - {id: "outflow_value", name: "Out Value", field: "outflow_value", width: 100, + {id: "outflow_value", name: wn._("Out Value"), field: "outflow_value", width: 100, formatter: this.currency_formatter}, - {id: "closing_value", name: "Closing Value", field: "closing_value", width: 100, + {id: "closing_value", name: wn._("Closing Value"), field: "closing_value", width: 100, formatter: this.currency_formatter}, ]; }, filters: [ - {fieldtype:"Select", label: "Brand", link:"Brand", + {fieldtype:"Select", label: wn._("Brand"), link:"Brand", default_value: "Select Brand...", filter: function(val, item, opts) { return val == opts.default_value || item.brand == val || item._show; }, link_formatter: {filter_input: "brand"}}, - {fieldtype:"Select", label: "Warehouse", link:"Warehouse", + {fieldtype:"Select", label: wn._("Warehouse"), link:"Warehouse", default_value: "Select Warehouse...", filter: function(val, item, opts, me) { return me.apply_zero_filter(val, item, opts, me); }}, - {fieldtype:"Select", label: "Project", link:"Project", + {fieldtype:"Select", label: wn._("Project"), link:"Project", default_value: "Select Project...", filter: function(val, item, opts, me) { return me.apply_zero_filter(val, item, opts, me); }, link_formatter: {filter_input: "project"}}, - {fieldtype:"Date", label: "From Date"}, - {fieldtype:"Label", label: "To"}, - {fieldtype:"Date", label: "To Date"}, - {fieldtype:"Button", label: "Refresh", icon:"icon-refresh icon-white", cssClass:"btn-info"}, - {fieldtype:"Button", label: "Reset Filters"} + {fieldtype:"Date", label: wn._("From Date")}, + {fieldtype:"Label", label: wn._("To")}, + {fieldtype:"Date", label: wn._("To Date")}, + {fieldtype:"Button", label: wn._("Refresh"), icon:"icon-refresh icon-white", cssClass:"btn-info"}, + {fieldtype:"Button", label: wn._("Reset Filters")} ], setup_plot_check: function() { From 65122328eb1656d1c74be41f627099bc98e9397d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A1rbara=20Perretti?= Date: Thu, 3 Oct 2013 16:37:38 -0300 Subject: [PATCH 086/200] Fix translate stock_ledger.js --- stock/page/stock_ledger/stock_ledger.js | 42 ++++++++++++------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/stock/page/stock_ledger/stock_ledger.js b/stock/page/stock_ledger/stock_ledger.js index c83fc0ec129..66071401868 100644 --- a/stock/page/stock_ledger/stock_ledger.js +++ b/stock/page/stock_ledger/stock_ledger.js @@ -4,7 +4,7 @@ wn.pages['stock-ledger'].onload = function(wrapper) { wn.ui.make_app_page({ parent: wrapper, - title: 'Stock Ledger', + title: wn._('Stock Ledger'), single_column: true }); @@ -17,7 +17,7 @@ wn.require("app/js/stock_grid_report.js"); erpnext.StockLedger = erpnext.StockGridReport.extend({ init: function(wrapper) { this._super({ - title: "Stock Ledger", + title: wn._("Stock Ledger"), page: wrapper, parent: $(wrapper).find('.layout-main'), appframe: wrapper.appframe, @@ -28,29 +28,29 @@ erpnext.StockLedger = erpnext.StockGridReport.extend({ setup_columns: function() { this.hide_balance = (this.is_default("item_code") || this.voucher_no) ? true : false; this.columns = [ - {id: "posting_datetime", name: "Posting Date", field: "posting_datetime", width: 120, + {id: "posting_datetime", name: wn._("Posting Date"), field: "posting_datetime", width: 120, formatter: this.date_formatter}, - {id: "item_code", name: "Item Code", field: "item_code", width: 160, + {id: "item_code", name: wn._("Item Code"), field: "item_code", width: 160, link_formatter: { filter_input: "item_code", open_btn: true, doctype: '"Item"', }}, - {id: "description", name: "Description", field: "description", width: 200, + {id: "description", name: wn._("Description"), field: "description", width: 200, formatter: this.text_formatter}, - {id: "warehouse", name: "Warehouse", field: "warehouse", width: 100, + {id: "warehouse", name: wn._("Warehouse"), field: "warehouse", width: 100, link_formatter: {filter_input: "warehouse"}}, - {id: "brand", name: "Brand", field: "brand", width: 100}, - {id: "stock_uom", name: "UOM", field: "stock_uom", width: 100}, - {id: "qty", name: "Qty", field: "qty", width: 100, + {id: "brand", name: wn._("Brand"), field: "brand", width: 100}, + {id: "stock_uom", name: wn._("UOM"), field: "stock_uom", width: 100}, + {id: "qty", name: wn._("Qty"), field: "qty", width: 100, formatter: this.currency_formatter}, - {id: "balance", name: "Balance Qty", field: "balance", width: 100, + {id: "balance", name: wn._("Balance Qty"), field: "balance", width: 100, formatter: this.currency_formatter, hidden: this.hide_balance}, - {id: "balance_value", name: "Balance Value", field: "balance_value", width: 100, + {id: "balance_value", name: wn._("Balance Value"), field: "balance_value", width: 100, formatter: this.currency_formatter, hidden: this.hide_balance}, - {id: "voucher_type", name: "Voucher Type", field: "voucher_type", width: 120}, - {id: "voucher_no", name: "Voucher No", field: "voucher_no", width: 160, + {id: "voucher_type", name: wn._("Voucher Type"), field: "voucher_type", width: 120}, + {id: "voucher_no", name: wn._("Voucher No"), field: "voucher_no", width: 160, link_formatter: { filter_input: "voucher_no", open_btn: true, @@ -60,11 +60,11 @@ erpnext.StockLedger = erpnext.StockGridReport.extend({ }, filters: [ - {fieldtype:"Select", label: "Warehouse", link:"Warehouse", + {fieldtype:"Select", label: wn._("Warehouse"), link:"Warehouse", default_value: "Select Warehouse...", filter: function(val, item, opts) { return item.warehouse == val || val == opts.default_value; }}, - {fieldtype:"Link", label: "Item Code", link:"Item", default_value: "Select Item...", + {fieldtype:"Link", label: wn._("Item Code"), link:"Item", default_value: "Select Item...", filter: function(val, item, opts) { return item.item_code == val || !val; }}, @@ -72,20 +72,20 @@ erpnext.StockLedger = erpnext.StockGridReport.extend({ default_value: "Select Brand...", filter: function(val, item, opts) { return val == opts.default_value || item.brand == val || item._show; }, link_formatter: {filter_input: "brand"}}, - {fieldtype:"Data", label: "Voucher No", + {fieldtype:"Data", label: wn._("Voucher No"), filter: function(val, item, opts) { if(!val) return true; return (item.voucher_no && item.voucher_no.indexOf(val)!=-1); }}, - {fieldtype:"Date", label: "From Date", filter: function(val, item) { + {fieldtype:"Date", label: wn._("From Date"), filter: function(val, item) { return dateutil.str_to_obj(val) <= dateutil.str_to_obj(item.posting_date); }}, - {fieldtype:"Label", label: "To"}, - {fieldtype:"Date", label: "To Date", filter: function(val, item) { + {fieldtype:"Label", label: wn._("To")}, + {fieldtype:"Date", label: wn._("To Date"), filter: function(val, item) { return dateutil.str_to_obj(val) >= dateutil.str_to_obj(item.posting_date); }}, - {fieldtype:"Button", label: "Refresh", icon:"icon-refresh icon-white", cssClass:"btn-info"}, - {fieldtype:"Button", label: "Reset Filters"} + {fieldtype:"Button", label: wn._("Refresh"), icon:"icon-refresh icon-white", cssClass:"btn-info"}, + {fieldtype:"Button", label: wn._("Reset Filters")} ], setup_filters: function() { From 301ce71c013c3b74943f03db927152e747e41ecf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A1rbara=20Perretti?= Date: Thu, 3 Oct 2013 17:28:23 -0300 Subject: [PATCH 087/200] Fix translate stock_level.js --- stock/page/stock_level/stock_level.js | 56 +++++++++++++-------------- 1 file changed, 28 insertions(+), 28 deletions(-) diff --git a/stock/page/stock_level/stock_level.js b/stock/page/stock_level/stock_level.js index df7c8c5d4d5..a6cc6a8209d 100644 --- a/stock/page/stock_level/stock_level.js +++ b/stock/page/stock_level/stock_level.js @@ -4,7 +4,7 @@ wn.pages['stock-level'].onload = function(wrapper) { wn.ui.make_app_page({ parent: wrapper, - title: 'Stock Level', + title: wn._('Stock Level'), single_column: true }); @@ -22,7 +22,7 @@ erpnext.StockLevel = erpnext.StockGridReport.extend({ var me = this; this._super({ - title: "Stock Level", + title: wn._("Stock Level"), page: wrapper, parent: $(wrapper).find('.layout-main'), appframe: wrapper.appframe, @@ -37,70 +37,70 @@ erpnext.StockLevel = erpnext.StockGridReport.extend({ Projected Qty = Actual Qty + Planned Qty + Requested Qty \ + Ordered Qty - Reserved Qty \
    \ -
  • Actual Qty: Quantity available in the warehouse.
  • \ -
  • Planned Qty: Quantity, for which, Production Order has been raised, \ - but is pending to be manufactured.
  • \ -
  • Requested Qty: Quantity requested for purchase, but not ordered.
  • \ -
  • Ordered Qty: Quantity ordered for purchase, but not received.
  • \ -
  • Reserved Qty: Quantity ordered for sale, but not delivered.
  • \ -
\ +
  • "+wn._("Actual Qty: Quantity available in the warehouse.") +"
  • "+ + "
  • "+wn._("Planned Qty: Quantity, for which, Production Order has been raised,")+ + wn._("but is pending to be manufactured.")+ "
  • " + + "
  • "+wn._("Requested Qty: Quantity requested for purchase, but not ordered.") + "
  • " + + "
  • " + wn._("Ordered Qty: Quantity ordered for purchase, but not received.")+ "
  • " + + "
  • " + wn._("Reserved Qty: Quantity ordered for sale, but not delivered.") + "
  • " + + " \ "); }); }, setup_columns: function() { this.columns = [ - {id: "item_code", name: "Item Code", field: "item_code", width: 160, + {id: "item_code", name: wn._("Item Code"), field: "item_code", width: 160, link_formatter: { filter_input: "item_code", open_btn: true, doctype: '"Item"', }}, - {id: "item_name", name: "Item Name", field: "item_name", width: 100, + {id: "item_name", name: wn._("Item Name"), field: "item_name", width: 100, formatter: this.text_formatter}, - {id: "description", name: "Description", field: "description", width: 200, + {id: "description", name: wn._("Description"), field: "description", width: 200, formatter: this.text_formatter}, - {id: "brand", name: "Brand", field: "brand", width: 100, + {id: "brand", name: wn._("Brand"), field: "brand", width: 100, link_formatter: {filter_input: "brand"}}, - {id: "warehouse", name: "Warehouse", field: "warehouse", width: 100, + {id: "warehouse", name: wn._("Warehouse"), field: "warehouse", width: 100, link_formatter: {filter_input: "warehouse"}}, - {id: "uom", name: "UOM", field: "uom", width: 60}, - {id: "actual_qty", name: "Actual Qty", + {id: "uom", name: wn._("UOM"), field: "uom", width: 60}, + {id: "actual_qty", name: wn._("Actual Qty"), field: "actual_qty", width: 80, formatter: this.currency_formatter}, - {id: "planned_qty", name: "Planned Qty", + {id: "planned_qty", name: wn._("Planned Qty"), field: "planned_qty", width: 80, formatter: this.currency_formatter}, - {id: "requested_qty", name: "Requested Qty", + {id: "requested_qty", name: wn._("Requested Qty"), field: "requested_qty", width: 80, formatter: this.currency_formatter}, - {id: "ordered_qty", name: "Ordered Qty", + {id: "ordered_qty", name: wn._("Ordered Qty"), field: "ordered_qty", width: 80, formatter: this.currency_formatter}, - {id: "reserved_qty", name: "Reserved Qty", + {id: "reserved_qty", name: wn._("Reserved Qty"), field: "reserved_qty", width: 80, formatter: this.currency_formatter}, - {id: "projected_qty", name: "Projected Qty", + {id: "projected_qty", name: wn._("Projected Qty"), field: "projected_qty", width: 80, formatter: this.currency_formatter}, - {id: "re_order_level", name: "Re-Order Level", + {id: "re_order_level", name: wn._("Re-Order Level"), field: "re_order_level", width: 80, formatter: this.currency_formatter}, - {id: "re_order_qty", name: "Re-Order Qty", + {id: "re_order_qty", name: wn._("Re-Order Qty"), field: "re_order_qty", width: 80, formatter: this.currency_formatter}, ]; }, filters: [ - {fieldtype:"Link", label: "Item Code", link:"Item", default_value: "Select Item...", + {fieldtype:"Link", label: wn._("Item Code"), link:"Item", default_value: "Select Item...", filter: function(val, item, opts) { return item.item_code == val || !val; }}, - {fieldtype:"Select", label: "Warehouse", link:"Warehouse", + {fieldtype:"Select", label: wn._("Warehouse"), link:"Warehouse", default_value: "Select Warehouse...", filter: function(val, item, opts) { return item.warehouse == val || val == opts.default_value; }}, - {fieldtype:"Select", label: "Brand", link:"Brand", + {fieldtype:"Select", label: wn._("Brand"), link:"Brand", default_value: "Select Brand...", filter: function(val, item, opts) { return val == opts.default_value || item.brand == val; }}, - {fieldtype:"Button", label: "Refresh", icon:"icon-refresh icon-white", cssClass:"btn-info"}, - {fieldtype:"Button", label: "Reset Filters"} + {fieldtype:"Button", label: wn._("Refresh"), icon:"icon-refresh icon-white", cssClass:"btn-info"}, + {fieldtype:"Button", label: wn._("Reset Filters")} ], setup_filters: function() { From 7090383de47b219f53184af720c937967e72d608 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A1rbara=20Perretti?= Date: Thu, 3 Oct 2013 17:32:34 -0300 Subject: [PATCH 088/200] Fix translate batch_wise_balance_history.js --- .../batch_wise_balance_history/batch_wise_balance_history.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/stock/report/batch_wise_balance_history/batch_wise_balance_history.js b/stock/report/batch_wise_balance_history/batch_wise_balance_history.js index a9d64777541..2b174872b2e 100644 --- a/stock/report/batch_wise_balance_history/batch_wise_balance_history.js +++ b/stock/report/batch_wise_balance_history/batch_wise_balance_history.js @@ -5,14 +5,14 @@ wn.query_reports["Batch-Wise Balance History"] = { "filters": [ { "fieldname":"from_date", - "label": "From Date", + "label": wn._("From Date"), "fieldtype": "Date", "width": "80", "default": sys_defaults.year_start_date, }, { "fieldname":"to_date", - "label": "To Date", + "label": wn._("To Date"), "fieldtype": "Date", "width": "80", "default": wn.datetime.get_today() From d2cdf7a2db31be9eeca2248804659089230f1245 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A1rbara=20Perretti?= Date: Thu, 3 Oct 2013 17:33:33 -0300 Subject: [PATCH 089/200] Fix translate itemwise_recommended_reorder_level.js --- .../itemwise_recommended_reorder_level.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/stock/report/itemwise_recommended_reorder_level/itemwise_recommended_reorder_level.js b/stock/report/itemwise_recommended_reorder_level/itemwise_recommended_reorder_level.js index 410feabf759..c22672865c6 100644 --- a/stock/report/itemwise_recommended_reorder_level/itemwise_recommended_reorder_level.js +++ b/stock/report/itemwise_recommended_reorder_level/itemwise_recommended_reorder_level.js @@ -5,13 +5,13 @@ wn.query_reports["Itemwise Recommended Reorder Level"] = { "filters": [ { "fieldname":"from_date", - "label": "From Date", + "label": wn._("From Date"), "fieldtype": "Date", "default": sys_defaults.year_start_date }, { "fieldname":"to_date", - "label": "To Date", + "label": wn._("To Date"), "fieldtype": "Date", "default": get_today() } From 7ce0267f8f50cafd5b3f88fc419f843934476315 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A1rbara=20Perretti?= Date: Thu, 3 Oct 2013 17:36:12 -0300 Subject: [PATCH 090/200] fix translate warehouse_wise_stock_balance.js --- .../warehouse_wise_stock_balance.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/stock/report/warehouse_wise_stock_balance/warehouse_wise_stock_balance.js b/stock/report/warehouse_wise_stock_balance/warehouse_wise_stock_balance.js index 942b4651bfd..1b0523cc12d 100644 --- a/stock/report/warehouse_wise_stock_balance/warehouse_wise_stock_balance.js +++ b/stock/report/warehouse_wise_stock_balance/warehouse_wise_stock_balance.js @@ -5,14 +5,14 @@ wn.query_reports["Warehouse-Wise Stock Balance"] = { "filters": [ { "fieldname":"from_date", - "label": "From Date", + "label": wn._("From Date"), "fieldtype": "Date", "width": "80", "default": sys_defaults.year_start_date, }, { "fieldname":"to_date", - "label": "To Date", + "label": wn._("To Date"), "fieldtype": "Date", "width": "80", "default": wn.datetime.get_today() From de4f8e692963d437cccfc7cca4680037b1238f1c Mon Sep 17 00:00:00 2001 From: Anand Doshi Date: Fri, 4 Oct 2013 13:20:39 +0530 Subject: [PATCH 091/200] [minor] [demo] fixed Lead.csv --- utilities/demo/demo_docs/Lead.csv | 134 +++++++++++++++--------------- 1 file changed, 67 insertions(+), 67 deletions(-) diff --git a/utilities/demo/demo_docs/Lead.csv b/utilities/demo/demo_docs/Lead.csv index c00ab441625..a97fe3bacb7 100644 --- a/utilities/demo/demo_docs/Lead.csv +++ b/utilities/demo/demo_docs/Lead.csv @@ -1,68 +1,68 @@ -Data Import Template,,,,,,,,,,,,,,,,,,,,,,,,,,, +Data Import Template,,,,,,,,,,,,,,,,,,,,,,,,,, Table:,Lead,,,,,,,,,,,,,,,,,,,,,,,,,, -,,,,,,,,,,,,,,,,,,,,,,,,,,, -,,,,,,,,,,,,,,,,,,,,,,,,,,, -Notes:,,,,,,,,,,,,,,,,,,,,,,,,,,, -Please do not change the template headings.,,,,,,,,,,,,,,,,,,,,,,,,,,, -First data column must be blank.,,,,,,,,,,,,,,,,,,,,,,,,,,, -Only mandatory fields are necessary for new records. You can delete non-mandatory columns if you wish.,,,,,,,,,,,,,,,,,,,,,,,,,,, -"For updating, you can update only selective columns.",,,,,,,,,,,,,,,,,,,,,,,,,,, -"If you are uploading new records, leave the ""name"" (ID) column blank.",,,,,,,,,,,,,,,,,,,,,,,,,,, -"If you are uploading new records, ""Naming Series"" becomes mandatory, if present.",,,,,,,,,,,,,,,,,,,,,,,,,,, -You can only upload upto 5000 records in one go. (may be less in some cases),,,,,,,,,,,,,,,,,,,,,,,,,,, -,,,,,,,,,,,,,,,,,,,,,,,,,,, -Column Labels,ID,Contact Name,Status,Naming Series,Company Name,Email Id,Source,From Customer,Campaign Name,Remark,Phone,Mobile No.,Fax,Website,Territory,Lead Type,Lead Owner,Market Segment,Industry,Request Type,Lost Reason,Next Contact By,Next Contact Date,Last Contact Date,Company,Unsubscribed,Blog Subscriber -Column Name:,name,lead_name,status,naming_series,company_name,email_id,source,customer,campaign_name,remark,phone,mobile_no,fax,website,territory,type,lead_owner,market_segment,industry,request_type,order_lost_reason,contact_by,contact_date,last_contact_date,company,unsubscribed,blog_subscriber -Mandatory:,Yes,Yes,Yes,No,No,No,No,No,No,No,No,No,No,No,No,No,No,No,No,No,No,No,No,No,No,No,No -Type:,Data (text),Data,Select,Select,Data,Data,Select,Link,Link,Small Text,Data,Data,Data,Data,Link,Select,Link,Select,Link,Select,Link,Link,Date,Date,Link,Check,Check -Info:,,,"One of: Open, Replied, Attempted to Contact, Contact in Future, Contacted, Interested, Not interested, Lead Lost, Converted","One of: LEAD, LEAD/10-11/, LEAD/MUMBAI/",,,"One of: Advertisement, Blog Post, Campaign, Call, Customer, Exhibition, Supplier, Website, Email",Valid Customer,Valid Campaign,,,,,,Valid Territory,"One of: Client, Channel Partner, Consultant",Valid Profile,"One of: Lower Income, Middle Income, Upper Income",Valid Industry Type,"One of: Product Enquiry, Request for Information, Suggestions, Other",Valid Quotation Lost Reason,Valid Profile,,,Valid Company,0 or 1,0 or 1 -Start entering data below this line,,,,,,,,,,,,,,,,,,,,,,,,,,, -,,Mart Lakeman,Passive,,Zany Brainy,MartLakeman@einrot.com,,,,,,,,,,,,,,,,,,,,, -,,Saga Lundqvist,Passive,,Patterson-Fletcher,SagaLundqvist@dayrep.com,,,,,,,,,,,,,,,,,,,,, -,,Adna Sjöberg,Passive,,Griff's Hamburgers,AdnaSjoberg@gustr.com,,,,,,,,,,,,,,,,,,,,, -,,Ida Svendsen,Passive,,Rhodes Furniture,IdaDSvendsen@superrito.com,,,,,,,,,,,,,,,,,,,,, -,,Emppu Hämeenniemi,Passive,,Burger Chef,EmppuHameenniemi@teleworm.us,,,,,,,,,,,,,,,,,,,,, -,,Eugenio Pisano,Passive,,Stratabiz,EugenioPisano@cuvox.de,,,,,,,,,,,,,,,,,,,,, -,,Semhar Hagos,Passive,,Home Quarters Warehouse,SemharHagos@einrot.com,,,,,,,,,,,,,,,,,,,,, -,,Branimira Ivanković,Passive,,Enviro Architectural Designs,BranimiraIvankovic@einrot.com,,,,,,,,,,,,,,,,,,,,, -,,Shelly Fields,Passive,,Ideal Garden Management,ShellyLFields@superrito.com,,,,,,,,,,,,,,,,,,,,, -,,Leo Mikulić,Passive,,Listen Up,LeoMikulic@gustr.com,,,,,,,,,,,,,,,,,,,,, -,,Denisa Jarošová,Passive,,I. Magnin,DenisaJarosova@teleworm.us,,,,,,,,,,,,,,,,,,,,, -,,Janek Rutkowski,Passive,,First Rate Choice,JanekRutkowski@dayrep.com,,,,,,,,,,,,,,,,,,,,, -,,美月 宇藤,Passive,,Multi Tech Development,mm@gustr.com,,,,,,,,,,,,,,,,,,,,, -,,Даниил Афанасьев,Passive,,National Auto Parts,dd@einrot.com,,,,,,,,,,,,,,,,,,,,, -,,Zorislav Petković,Passive,,Integra Investment Plan,ZorislavPetkovic@cuvox.de,,,,,,,,,,,,,,,,,,,,, -,,Nanao Niwa,Passive,,The Lawn Guru,NanaoNiwa@superrito.com,,,,,,,,,,,,,,,,,,,,, -,,Hreiðar Jörundsson,Passive,,Buena Vista Realty Service,HreiarJorundsson@armyspy.com,,,,,,,,,,,,,,,,,,,,, -,,Lai Chu,Passive,,Bountiful Harvest Health Food Store,ChuThiBichLai@einrot.com,,,,,,,,,,,,,,,,,,,,, -,,Victor Aksakov,Passive,,P. Samuels Men's Clothiers,VictorAksakov@dayrep.com,,,,,,,,,,,,,,,,,,,,, -,,Saidalim Bisliev,Passive,,Vinyl Fever,SaidalimBisliev@cuvox.de,,,,,,,,,,,,,,,,,,,,, -,,Totte Jakobsson,Passive,,Garden Master,TotteJakobsson@armyspy.com,,,,,,,,,,,,,,,,,,,,, -,,Naná Armas,Passive,,Big Apple,NanaArmasRobles@cuvox.de,,,,,,,,,,,,,,,,,,,,, -,,Walerian Duda,Passive,,Monk House Sales,WalerianDuda@dayrep.com,,,,,,,,,,,,,,,,,,,,, -,,Moarimikashi ,Passive,,ManCharm,Moarimikashi@teleworm.us,,,,,,,,,,,,,,,,,,,,, -,,Dobromił Dąbrowski ,Passive,,Custom Lawn Care,DobromilDabrowski@dayrep.com,,,,,,,,,,,,,,,,,,,,, -,,Teigan Sinclair,Passive,,The Serendipity Dip,TeiganSinclair@gustr.com,,,,,,,,,,,,,,,,,,,,, -,,Fahad Guirguis,Passive,,Cavages,FahadSaidGuirguis@gustr.com,,,,,,,,,,,,,,,,,,,,, -,,Morten Olsen,Passive,,Gallenkamp,MortenJOlsen@armyspy.com,,,,,,,,,,,,,,,,,,,,, -,,Christian Baecker,Passive,,Webcom Business Services,ChristianBaecker@armyspy.com,,,,,,,,,,,,,,,,,,,,, -,,Sebastianus Dohmen,Passive,,Accord Investments,SebastianusDohmen@cuvox.de,,,,,,,,,,,,,,,,,,,,, -,,Eero Koskinen,Passive,,American Appliance,EeroKoskinen@superrito.com,,,,,,,,,,,,,,,,,,,,, -,,富奎 盧,Passive,,Bettendorf's,LuFuKui@teleworm.us,,,,,,,,,,,,,,,,,,,,, -,,Milica Jelić,Passive,,House Of Denmark,MilicaJelic@dayrep.com,,,,,,,,,,,,,,,,,,,,, -,,Barbora Holubová,Passive,,10000 Auto Parts,BarboraHolubova@cuvox.de,,,,,,,,,,,,,,,,,,,,, -,,Marta Kos,Passive,,Mages,MartaKos@einrot.com,,,,,,,,,,,,,,,,,,,,, -,,Simret Zula,Passive,,CSK Auto,SimretZula@cuvox.de,,,,,,,,,,,,,,,,,,,,, -,,Kamil Chlubna,Passive,,Eagle Hardware & Garden,KamilChlubna@einrot.com,,,,,,,,,,,,,,,,,,,,, -,,Aceline Bolduc,Passive,,Rustler Steak House,AcelineBolduc@armyspy.com,,,,,,,,,,,,,,,,,,,,, -,,Lucie Stupková,Passive,,ABCO Foods,LucieStupkova@gustr.com,,,,,,,,,,,,,,,,,,,,, -,,Roland Solvik,Passive,,Trak Auto,RolandSolvik@cuvox.de,,,,,,,,,,,,,,,,,,,,, -,,Mekirinzukushitakufu ,Passive,,Choices,Mekirinzukushitakufu@teleworm.us,,,,,,,,,,,,,,,,,,,,, -,,Mukharbek Sultanovich,Passive,,Megatronic,MukharbekSultanovich@cuvox.de,,,,,,,,,,,,,,,,,,,,, -,,Osman Amanuel,Passive,,Handy Dan,OsmanAmanuel@dayrep.com,,,,,,,,,,,,,,,,,,,,, -,,幸子 阪部,Passive,,Channel Home Centers,dd@armyspy.com,,,,,,,,,,,,,,,,,,,,, -,,Masakazu Kamitani,Passive,,Honest Air Group,MasakazuKamitani@superrito.com,,,,,,,,,,,,,,,,,,,,, -,,Omran Sabbagh,Passive,,Pleasures and Pasttimes,OmranNuhaidSabbagh@einrot.com,,,,,,,,,,,,,,,,,,,,, -,,Rikako Matsumura,Passive,,Lazysize,RikakoMatsumura@einrot.com,,,,,,,,,,,,,,,,,,,,, -,,Anayolisa Chukwukadibia,Passive,,Prestiga-Biz,AnayolisaChukwukadibia@einrot.com,,,,,,,,,,,,,,,,,,,,, -,,Gudmunda Hinna,Passive,,Childs Restaurants,GudmundaHinna@armyspy.com,,,,,,,,,,,,,,,,,,,,, \ No newline at end of file +,,,,,,,,,,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,,,,,,,,,,, +Notes:,,,,,,,,,,,,,,,,,,,,,,,,,, +Please do not change the template headings.,,,,,,,,,,,,,,,,,,,,,,,,,, +First data column must be blank.,,,,,,,,,,,,,,,,,,,,,,,,,, +Only mandatory fields are necessary for new records. You can delete non-mandatory columns if you wish.,,,,,,,,,,,,,,,,,,,,,,,,,, +"For updating, you can update only selective columns.",,,,,,,,,,,,,,,,,,,,,,,,,, +"If you are uploading new records, leave the ""name"" (ID) column blank.",,,,,,,,,,,,,,,,,,,,,,,,,, +"If you are uploading new records, ""Naming Series"" becomes mandatory, if present.",,,,,,,,,,,,,,,,,,,,,,,,,, +You can only upload upto 5000 records in one go. (may be less in some cases),,,,,,,,,,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,,,,,,,,,,, +Column Labels,ID,Contact Name,Status,Naming Series,Company Name,Email Id,Source,From Customer,Campaign Name,Remark,Phone,Mobile No.,Fax,Website,Territory,Lead Type,Lead Owner,Market Segment,Industry,Request Type,Next Contact By,Next Contact Date,Last Contact Date,Company,Unsubscribed,Blog Subscriber +Column Name:,name,lead_name,status,naming_series,company_name,email_id,source,customer,campaign_name,remark,phone,mobile_no,fax,website,territory,type,lead_owner,market_segment,industry,request_type,contact_by,contact_date,last_contact_date,company,unsubscribed,blog_subscriber +Mandatory:,Yes,Yes,Yes,No,No,No,No,No,No,No,No,No,No,No,No,No,No,No,No,No,No,No,No,No,No,No +Type:,Data (text),Data,Select,Select,Data,Data,Select,Link,Link,Small Text,Data,Data,Data,Data,Link,Select,Link,Select,Link,Select,Link,Date,Date,Link,Check,Check +Info:,,,"Lead, Open, Replied, Opportunity, Interested, Converted, Do Not Contact","One of: LEAD, LEAD/10-11/, LEAD/MUMBAI/",,,"One of: Advertisement, Blog Post, Campaign, Call, Customer, Exhibition, Supplier, Website, Email",Valid Customer,Valid Campaign,,,,,,Valid Territory,"One of: Client, Channel Partner, Consultant",Valid Profile,"One of: Lower Income, Middle Income, Upper Income",Valid Industry Type,"One of: Product Enquiry, Request for Information, Suggestions, Other",Valid Profile,,,Valid Company,0 or 1,0 or 1 +Start entering data below this line,,,,,,,,,,,,,,,,,,,,,,,,,, +,,Mart Lakeman,Lead,,Zany Brainy,MartLakeman@einrot.com,,,,,,,,,,,,,,,,,,,, +,,Saga Lundqvist,Lead,,Patterson-Fletcher,SagaLundqvist@dayrep.com,,,,,,,,,,,,,,,,,,,, +,,Adna Sjöberg,Lead,,Griff's Hamburgers,AdnaSjoberg@gustr.com,,,,,,,,,,,,,,,,,,,, +,,Ida Svendsen,Lead,,Rhodes Furniture,IdaDSvendsen@superrito.com,,,,,,,,,,,,,,,,,,,, +,,Emppu Hämeenniemi,Lead,,Burger Chef,EmppuHameenniemi@teleworm.us,,,,,,,,,,,,,,,,,,,, +,,Eugenio Pisano,Lead,,Stratabiz,EugenioPisano@cuvox.de,,,,,,,,,,,,,,,,,,,, +,,Semhar Hagos,Lead,,Home Quarters Warehouse,SemharHagos@einrot.com,,,,,,,,,,,,,,,,,,,, +,,Branimira Ivanković,Lead,,Enviro Architectural Designs,BranimiraIvankovic@einrot.com,,,,,,,,,,,,,,,,,,,, +,,Shelly Fields,Lead,,Ideal Garden Management,ShellyLFields@superrito.com,,,,,,,,,,,,,,,,,,,, +,,Leo Mikulić,Lead,,Listen Up,LeoMikulic@gustr.com,,,,,,,,,,,,,,,,,,,, +,,Denisa Jarošová,Lead,,I. Magnin,DenisaJarosova@teleworm.us,,,,,,,,,,,,,,,,,,,, +,,Janek Rutkowski,Lead,,First Rate Choice,JanekRutkowski@dayrep.com,,,,,,,,,,,,,,,,,,,, +,,美月 宇藤,Lead,,Multi Tech Development,mm@gustr.com,,,,,,,,,,,,,,,,,,,, +,,Даниил Афанасьев,Lead,,National Auto Parts,dd@einrot.com,,,,,,,,,,,,,,,,,,,, +,,Zorislav Petković,Lead,,Integra Investment Plan,ZorislavPetkovic@cuvox.de,,,,,,,,,,,,,,,,,,,, +,,Nanao Niwa,Lead,,The Lawn Guru,NanaoNiwa@superrito.com,,,,,,,,,,,,,,,,,,,, +,,Hreiðar Jörundsson,Lead,,Buena Vista Realty Service,HreiarJorundsson@armyspy.com,,,,,,,,,,,,,,,,,,,, +,,Lai Chu,Lead,,Bountiful Harvest Health Food Store,ChuThiBichLai@einrot.com,,,,,,,,,,,,,,,,,,,, +,,Victor Aksakov,Lead,,P. Samuels Men's Clothiers,VictorAksakov@dayrep.com,,,,,,,,,,,,,,,,,,,, +,,Saidalim Bisliev,Lead,,Vinyl Fever,SaidalimBisliev@cuvox.de,,,,,,,,,,,,,,,,,,,, +,,Totte Jakobsson,Lead,,Garden Master,TotteJakobsson@armyspy.com,,,,,,,,,,,,,,,,,,,, +,,Naná Armas,Lead,,Big Apple,NanaArmasRobles@cuvox.de,,,,,,,,,,,,,,,,,,,, +,,Walerian Duda,Lead,,Monk House Sales,WalerianDuda@dayrep.com,,,,,,,,,,,,,,,,,,,, +,,Moarimikashi ,Lead,,ManCharm,Moarimikashi@teleworm.us,,,,,,,,,,,,,,,,,,,, +,,Dobromił Dąbrowski ,Lead,,Custom Lawn Care,DobromilDabrowski@dayrep.com,,,,,,,,,,,,,,,,,,,, +,,Teigan Sinclair,Lead,,The Serendipity Dip,TeiganSinclair@gustr.com,,,,,,,,,,,,,,,,,,,, +,,Fahad Guirguis,Lead,,Cavages,FahadSaidGuirguis@gustr.com,,,,,,,,,,,,,,,,,,,, +,,Morten Olsen,Lead,,Gallenkamp,MortenJOlsen@armyspy.com,,,,,,,,,,,,,,,,,,,, +,,Christian Baecker,Lead,,Webcom Business Services,ChristianBaecker@armyspy.com,,,,,,,,,,,,,,,,,,,, +,,Sebastianus Dohmen,Lead,,Accord Investments,SebastianusDohmen@cuvox.de,,,,,,,,,,,,,,,,,,,, +,,Eero Koskinen,Lead,,American Appliance,EeroKoskinen@superrito.com,,,,,,,,,,,,,,,,,,,, +,,富奎 盧,Lead,,Bettendorf's,LuFuKui@teleworm.us,,,,,,,,,,,,,,,,,,,, +,,Milica Jelić,Lead,,House Of Denmark,MilicaJelic@dayrep.com,,,,,,,,,,,,,,,,,,,, +,,Barbora Holubová,Lead,,10000 Auto Parts,BarboraHolubova@cuvox.de,,,,,,,,,,,,,,,,,,,, +,,Marta Kos,Lead,,Mages,MartaKos@einrot.com,,,,,,,,,,,,,,,,,,,, +,,Simret Zula,Lead,,CSK Auto,SimretZula@cuvox.de,,,,,,,,,,,,,,,,,,,, +,,Kamil Chlubna,Lead,,Eagle Hardware & Garden,KamilChlubna@einrot.com,,,,,,,,,,,,,,,,,,,, +,,Aceline Bolduc,Lead,,Rustler Steak House,AcelineBolduc@armyspy.com,,,,,,,,,,,,,,,,,,,, +,,Lucie Stupková,Lead,,ABCO Foods,LucieStupkova@gustr.com,,,,,,,,,,,,,,,,,,,, +,,Roland Solvik,Lead,,Trak Auto,RolandSolvik@cuvox.de,,,,,,,,,,,,,,,,,,,, +,,Mekirinzukushitakufu ,Lead,,Choices,Mekirinzukushitakufu@teleworm.us,,,,,,,,,,,,,,,,,,,, +,,Mukharbek Sultanovich,Lead,,Megatronic,MukharbekSultanovich@cuvox.de,,,,,,,,,,,,,,,,,,,, +,,Osman Amanuel,Lead,,Handy Dan,OsmanAmanuel@dayrep.com,,,,,,,,,,,,,,,,,,,, +,,幸子 阪部,Lead,,Channel Home Centers,dd@armyspy.com,,,,,,,,,,,,,,,,,,,, +,,Masakazu Kamitani,Lead,,Honest Air Group,MasakazuKamitani@superrito.com,,,,,,,,,,,,,,,,,,,, +,,Omran Sabbagh,Lead,,Pleasures and Pasttimes,OmranNuhaidSabbagh@einrot.com,,,,,,,,,,,,,,,,,,,, +,,Rikako Matsumura,Lead,,Lazysize,RikakoMatsumura@einrot.com,,,,,,,,,,,,,,,,,,,, +,,Anayolisa Chukwukadibia,Lead,,Prestiga-Biz,AnayolisaChukwukadibia@einrot.com,,,,,,,,,,,,,,,,,,,, +,,Gudmunda Hinna,Lead,,Childs Restaurants,GudmundaHinna@armyspy.com,,,,,,,,,,,,,,,,,,,, \ No newline at end of file From acc876e0d7b444a857b6618f8759394fb7d0e5b1 Mon Sep 17 00:00:00 2001 From: Rushabh Mehta Date: Fri, 4 Oct 2013 13:33:24 +0530 Subject: [PATCH 092/200] [minor] [fix] status updater, only change communication status when called explicitly --- controllers/status_updater.py | 16 ++++++++++------ patches/october_2013/p03_crm_update_status.py | 18 +++++++++--------- 2 files changed, 19 insertions(+), 15 deletions(-) diff --git a/controllers/status_updater.py b/controllers/status_updater.py index e457fa957ef..b2a0e17a258 100644 --- a/controllers/status_updater.py +++ b/controllers/status_updater.py @@ -88,17 +88,21 @@ class StatusUpdater(DocListController): webnotes.conn.set_value(self.doc.doctype, self.doc.name, "status", self.doc.status) def on_communication(self): + self.communication_set = True self.set_status(update=True) + del self.communication_set def communication_received(self): - last_comm = self.doclist.get({"doctype":"Communication"}) - if last_comm: - return last_comm[-1].sent_or_received == "Received" + if getattr(self, "communication_set", False): + last_comm = self.doclist.get({"doctype":"Communication"}) + if last_comm: + return last_comm[-1].sent_or_received == "Received" def communication_sent(self): - last_comm = self.doclist.get({"doctype":"Communication"}) - if last_comm: - return last_comm[-1].sent_or_received == "Sent" + if getattr(self, "communication_set", False): + last_comm = self.doclist.get({"doctype":"Communication"}) + if last_comm: + return last_comm[-1].sent_or_received == "Sent" def validate_qty(self): """ diff --git a/patches/october_2013/p03_crm_update_status.py b/patches/october_2013/p03_crm_update_status.py index 73ed1b1c78c..07a70c642a9 100644 --- a/patches/october_2013/p03_crm_update_status.py +++ b/patches/october_2013/p03_crm_update_status.py @@ -36,12 +36,12 @@ def execute(): webnotes.conn.sql("""update `tab%s` set status=%s where status=%s""" % \ (dt, "%s", "%s"), (status[1], status[0])) - # for dt in ["Lead", "Opportunity"]: - # for name in webnotes.conn.sql_list("""select name from `tab%s`""" % dt): - # bean = webnotes.bean(dt, name) - # before_status = bean.doc.status - # bean.get_controller().set_status() - # - # if bean.doc.status != before_status: - # webnotes.conn.sql("""update `tab%s` set status=%s where name=%s""" % (dt, "%s", "%s"), - # (bean.doc.status, name)) + for dt in ["Lead", "Opportunity"]: + for name in webnotes.conn.sql_list("""select name from `tab%s`""" % dt): + bean = webnotes.bean(dt, name) + before_status = bean.doc.status + bean.get_controller().set_status() + + if bean.doc.status != before_status: + webnotes.conn.sql("""update `tab%s` set status=%s where name=%s""" % (dt, "%s", "%s"), + (bean.doc.status, name)) From ae307e8bf835d0587877b7cd3818be20596288e7 Mon Sep 17 00:00:00 2001 From: Rushabh Mehta Date: Fri, 4 Oct 2013 17:48:05 +0530 Subject: [PATCH 093/200] [setup wizard] Started - WIP --- setup/page/setup_wizard/__init__.py | 0 setup/page/setup_wizard/setup_wizard.js | 217 +++++++++++++++++++++++ setup/page/setup_wizard/setup_wizard.txt | 32 ++++ 3 files changed, 249 insertions(+) create mode 100644 setup/page/setup_wizard/__init__.py create mode 100644 setup/page/setup_wizard/setup_wizard.js create mode 100644 setup/page/setup_wizard/setup_wizard.txt diff --git a/setup/page/setup_wizard/__init__.py b/setup/page/setup_wizard/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/setup/page/setup_wizard/setup_wizard.js b/setup/page/setup_wizard/setup_wizard.js new file mode 100644 index 00000000000..b88f6e6c13e --- /dev/null +++ b/setup/page/setup_wizard/setup_wizard.js @@ -0,0 +1,217 @@ +wn.pages['setup-wizard'].onload = function(wrapper) { + erpnext.wiz = new wn.wiz.Wizard({ + parent: wrapper, + title: wn._("ERPNext Setup Guide"), + slides: [ + // User + { + title: wn._("The First User"), + fields: [ + {"fieldname": "first_name", "label": wn._("First Name"), "fieldtype": "Data", reqd:1}, + {"fieldname": "last_name", "label": wn._("Last Name"), "fieldtype": "Data", reqd:1}, + ], + help: wn._('The first user will become the System Manager (you can change that later).') + }, + + // Organization + { + title: wn._("The Organization"), + fields: [ + {fieldname:'company_name', label: wn._('Company Name'), fieldtype:'Data', reqd:1, + placeholder: 'e.g. "My Company LLC"'}, + {fieldname:'company_abbr', label: wn._('Company Abbreviation'), fieldtype:'Data', + placeholder:'e.g. "MC"',reqd:1}, + {fieldname:'company_tagline', label: wn._('What does it do?'), fieldtype:'Data', + placeholder:'e.g. "Build tools for builders"',reqd:1}, + ], + help: wn._('The name of your company for which you are setting up this system.'), + onload: function(slide) { + slide.get_input("company_name").on("change", function() { + var parts = slide.get_input("company_name").val().split(" "); + var abbr = $.map(parts, function(p) { return p ? p.substr(0,1) : null }).join(""); + slide.get_input("company_abbr").val(abbr.toUpperCase()); + }); + } + }, + + // Country + { + title: wn._("Country, Timezone and Currency"), + fields: [ + {fieldname:'country', label: wn._('Country'), reqd:1, + options: "", fieldtype: 'Select'}, + {fieldname:'currency', label: wn._('Default Currency'), reqd:1, + options: "", fieldtype: 'Select'}, + {fieldname:'timezone', label: wn._('Time Zone'), reqd:1, + options: "", fieldtype: 'Select'}, + ], + help: wn._('Select your home country and check the timezone and currency.'), + onload: function(slide, form) { + wn.call({ + method:"webnotes.country_info.get_country_timezone_info", + callback: function(data) { + erpnext.country_info = data.message.country_info; + erpnext.all_timezones = data.message.all_timezones; + slide.get_input("country").empty() + .add_options([""].concat(keys(erpnext.country_info).sort())); + slide.get_input("currency").empty() + .add_options(wn.utils.unique([""].concat($.map(erpnext.country_info, + function(opts, country) { return opts.currency; }))).sort()); + slide.get_input("timezone").empty() + .add_options([""].concat(erpnext.all_timezones)); + } + }) + + slide.get_input("country").on("change", function() { + var country = slide.get_input("country").val(); + var $timezone = slide.get_input("timezone"); + $timezone.empty(); + // add country specific timezones first + if(country){ + var timezone_list = erpnext.country_info[country].timezones || []; + $timezone.add_options(timezone_list.sort()); + slide.get_input("currency").val(erpnext.country_info[country].currency); + } + // add all timezones at the end, so that user has the option to change it to any timezone + $timezone.add_options([""].concat(erpnext.all_timezones)); + + }); + } + }, + + // Logo + { + title: wn._("Logo and Letter Heads"), + help: wn._('Upload your letter head and logo - you can edit them later.'), + html: '

    ' + wn._('Upload Logo') + '


    ' + +'

    ' + wn._('Upload Letter Head') + '

    ', + onload: function(slide) { + wn.upload.make({ + parent: slide.$wrapper.find(".upload-area-letter-head").css({"margin-left": "10px"}), + on_attach: function(fileobj) { + console.log(fileobj); + } + }); + + wn.upload.make({ + parent: slide.$wrapper.find(".upload-area-logo").css({"margin-left": "10px"}), + on_attach: function(fileobj) { + console.log(fileobj); + } + }); + } + + }, + + // Taxes + { + "title": wn._("Add Taxes"), + "help": wn._("List your tax heads (e.g. VAT, Excise) (upto 3) and their standard rates. This will create a standard template, you can edit and add more later."), + "fields": [ + {fieldtype:"Data", fieldname:"tax_1", label:"Tax 1", placeholder:"e.g. VAT"}, + {fieldtype:"Data", fieldname:"tax_rate_1", label:"Rate for Tax 1 (%)", placeholder:"e.g. 5"}, + {fieldtype:"Data", fieldname:"tax_2", label:"Tax 2", placeholder:"e.g. Customs Duty"}, + {fieldtype:"Data", fieldname:"tax_rate_2", label:"Rate for Tax 2 (%)", placeholder:"e.g. 5"}, + {fieldtype:"Data", fieldname:"tax_3", label:"Tax 3", placeholder:"e.g. Excise"}, + {fieldtype:"Data", fieldname:"tax_rate_3", label:"Rate for Tax 3 (%)", placeholder:"e.g. 5"}, + ], + onload: function(slide) { + slide.form.fields_dict.tax_rate_1.$wrapper.css("margin-left", "50%"); + slide.form.fields_dict.tax_rate_2.$wrapper.css("margin-left", "50%"); + slide.form.fields_dict.tax_rate_3.$wrapper.css("margin-left", "50%"); + } + } + + // + ] + + }) +} + +wn.pages['setup-wizard'].onshow = function(wrapper) { + erpnext.wiz.show(wn.get_route()[1] || "0"); +} + +wn.provide("wn.wiz"); + +wn.wiz.Wizard = Class.extend({ + init: function(opts) { + $.extend(this, opts); + this.slide_dict = {}; + wn.set_route("setup-wizard", "0"); + }, + show: function(id) { + id = cint(id); + if(this.current_slide && this.current_slide.id===id) + return; + if(!this.slide_dict[id]) { + this.slide_dict[id] = new wn.wiz.WizardSlide($.extend(this.slides[id], {wiz:this, id:id})); + this.slide_dict[id].make(); + } + + if(this.current_slide) + this.current_slide.$wrapper.toggle(false); + + this.current_slide = this.slide_dict[id]; + this.current_slide.$wrapper.toggle(true); + }, +}); + +wn.wiz.WizardSlide = Class.extend({ + init: function(opts) { + $.extend(this, opts); + }, + make: function() { + var me = this; + this.$wrapper = $(repl('
    \ +
    %(main_title)s: %(title)s
    \ +
    \ +
    \ +
    \ +
    \ +
    \ +
    \ +

    %(title)s

    %(help)s

    \ +
    \ +
    \ + \ +
    \ +
    ', {help:this.help, title:this.title, main_title:this.wiz.title, width: (flt(this.id + 1) / this.wiz.slides.length) * 100})) + .appendTo(this.wiz.parent); + + this.body = this.$wrapper.find(".form")[0]; + + if(this.fields) { + this.form = new wn.ui.FieldGroup({ + fields: this.fields, + body: this.body + }); + this.form.make(); + } else { + $(this.body).html(this.html) + } + + if(this.id > 0) { + this.$prev = $("") + .click(function() { wn.set_route("setup-wizard", me.id-1 + ""); }) + .appendTo(this.$wrapper.find(".footer")) + .css({"margin-right": "5px"}); + } + if(this.id+1 < this.wiz.slides.length) { + this.$next = $("") + .click(function() { wn.set_route("setup-wizard", me.id+1 + ""); }) + .appendTo(this.$wrapper.find(".footer")); + } else { + this.$complete = $("") + .click(function() { me.wiz.complete(); }).appendTo(this.$wrapper.find(".footer")); + } + + if(this.onload) { + this.onload(this); + } + + }, + get_input: function(fn) { + return this.form.get_input(fn); + } +}) \ No newline at end of file diff --git a/setup/page/setup_wizard/setup_wizard.txt b/setup/page/setup_wizard/setup_wizard.txt new file mode 100644 index 00000000000..996fd1a0591 --- /dev/null +++ b/setup/page/setup_wizard/setup_wizard.txt @@ -0,0 +1,32 @@ +[ + { + "creation": "2013-10-04 13:49:33", + "docstatus": 0, + "modified": "2013-10-04 13:49:33", + "modified_by": "Administrator", + "owner": "Administrator" + }, + { + "doctype": "Page", + "module": "Setup", + "name": "__common__", + "page_name": "setup-wizard", + "standard": "Yes", + "title": "Setup Wizard" + }, + { + "doctype": "Page Role", + "name": "__common__", + "parent": "setup-wizard", + "parentfield": "roles", + "parenttype": "Page", + "role": "System Manager" + }, + { + "doctype": "Page", + "name": "setup-wizard" + }, + { + "doctype": "Page Role" + } +] \ No newline at end of file From 3df4f8898b82158537c2f182c36c3abdf2abc0e0 Mon Sep 17 00:00:00 2001 From: Anand Doshi Date: Fri, 4 Oct 2013 21:19:30 +0530 Subject: [PATCH 094/200] [minor] crm funnel first cut --- selling/page/crm_funnel/__init__.py | 0 selling/page/crm_funnel/crm_funnel.css | 3 + selling/page/crm_funnel/crm_funnel.js | 176 +++++++++++++++++++++++++ selling/page/crm_funnel/crm_funnel.py | 33 +++++ selling/page/crm_funnel/crm_funnel.txt | 33 +++++ 5 files changed, 245 insertions(+) create mode 100644 selling/page/crm_funnel/__init__.py create mode 100644 selling/page/crm_funnel/crm_funnel.css create mode 100644 selling/page/crm_funnel/crm_funnel.js create mode 100644 selling/page/crm_funnel/crm_funnel.py create mode 100644 selling/page/crm_funnel/crm_funnel.txt diff --git a/selling/page/crm_funnel/__init__.py b/selling/page/crm_funnel/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/selling/page/crm_funnel/crm_funnel.css b/selling/page/crm_funnel/crm_funnel.css new file mode 100644 index 00000000000..89e904fcfc9 --- /dev/null +++ b/selling/page/crm_funnel/crm_funnel.css @@ -0,0 +1,3 @@ +.funnel-wrapper { + margin: 15px; +} \ No newline at end of file diff --git a/selling/page/crm_funnel/crm_funnel.js b/selling/page/crm_funnel/crm_funnel.js new file mode 100644 index 00000000000..a2d2b934790 --- /dev/null +++ b/selling/page/crm_funnel/crm_funnel.js @@ -0,0 +1,176 @@ +// Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. +// License: GNU General Public License v3. See license.txt + +wn.pages['crm-funnel'].onload = function(wrapper) { + wn.ui.make_app_page({ + parent: wrapper, + title: 'CRM Funnel', + single_column: true + }); + + wrapper.crm_funnel = new erpnext.CRMFunnel(wrapper); +} + +erpnext.CRMFunnel = Class.extend({ + init: function(wrapper) { + var me = this; + // 0 setTimeout hack - this gives time for canvas to get width and height + setTimeout(function() { + me.setup(wrapper); + me.get_data(); + }, 0); + }, + + setup: function(wrapper) { + var me = this; + + this.elements = { + layout: $(wrapper).find(".layout-main"), + from_date: wrapper.appframe.add_date("From Date"), + to_date: wrapper.appframe.add_date("To Date"), + refresh_btn: wrapper.appframe.add_button("Refresh", + function() { me.get_data(); }, "icon-refresh"), + }; + + this.elements.no_data = $('
    No Data
    ') + .toggle(false) + .appendTo(this.elements.layout); + + this.elements.funnel_wrapper = $('
    ') + .appendTo(this.elements.layout); + + this.options = { + from_date: wn.datetime.get_today(), + to_date: wn.datetime.add_months(wn.datetime.get_today(), -1) + }; + + // set defaults and bind on change + $.each(this.options, function(k, v) { + me.elements[k].val(wn.datetime.str_to_user(v)); + me.elements[k].on("change", function() { + me.options[k] = wn.datetime.user_to_str($(this).val()); + me.get_data(); + }); + }); + + // bind refresh + this.elements.refresh_btn.on("click", function() { + me.get_data(this); + }); + + // bind resize + $(window).resize(function() { + me.render(); + }); + }, + + get_data: function(btn) { + var me = this; + wn.call({ + module: "selling", + page: "crm_funnel", + method: "get_funnel_data", + args: { + from_date: this.options.from_date, + to_date: this.options.to_date + }, + btn: btn, + callback: function(r) { + if(!r.exc) { + me.options.data = r.message; + me.render(); + } + } + }); + }, + + render: function() { + var me = this; + this.prepare(); + + var context = this.elements.context, + x_start = 0.0, + x_end = this.options.width, + x_mid = (x_end - x_start) / 2.0, + y = 0, + y_old = 0.0; + + if(this.options.total_value === 0) { + this.elements.no_data.toggle(true); + return; + } + + this.options.data.forEach(function(d) { + context.fillStyle = d.color; + context.strokeStyle = d.color; + me.draw_triangle(x_start, x_mid, x_end, y, me.options.height); + + y_old = y; + + // new y + y = y + (me.options.height * d.value / me.options.total_value); + + // new x + var half_side = (me.options.height - y) / Math.sqrt(3); + x_start = x_mid - half_side; + x_end = x_mid + half_side; + + var y_mid = y_old + (y - y_old) / 2.0; + + me.draw_legend(x_mid, y_mid, me.options.width, me.options.height, d.value + " - " + d.title); + }); + }, + + prepare: function() { + this.elements.no_data.toggle(false); + + // calculate width and height options + this.options.width = $(this.elements.funnel_wrapper).width() * 2.0 / 3.0; + this.options.height = (Math.sqrt(3) * this.options.width) / 2.0; + + // calculate total value + this.options.total_value = this.options.data.reduce( + function(prev, curr) { return prev + curr.value; }, 0.0); + + this.elements.canvas = $('') + .appendTo(this.elements.funnel_wrapper.empty()) + .attr("width", $(this.elements.funnel_wrapper).width()) + .attr("height", this.options.height); + + this.elements.context = this.elements.canvas.get(0).getContext("2d"); + }, + + draw_triangle: function(x_start, x_mid, x_end, y, height) { + var context = this.elements.context; + context.beginPath(); + context.moveTo(x_start, y); + context.lineTo(x_end, y); + context.lineTo(x_mid, height); + context.lineTo(x_start, y); + context.closePath(); + context.fill(); + }, + + draw_legend: function(x_mid, y_mid, width, height, title) { + var context = this.elements.context; + + // draw line + context.beginPath(); + context.moveTo(x_mid, y_mid); + context.lineTo(width, y_mid); + context.closePath(); + context.stroke(); + + // draw circle + context.beginPath(); + context.arc(width, y_mid, 5, 0, Math.PI * 2, false); + context.closePath(); + context.fill(); + + // draw text + context.fillStyle = "black"; + context.textBaseline = "middle"; + context.font = "1.1em sans-serif"; + context.fillText(title, width + 20, y_mid); + } +}); \ No newline at end of file diff --git a/selling/page/crm_funnel/crm_funnel.py b/selling/page/crm_funnel/crm_funnel.py new file mode 100644 index 00000000000..be0aebe7bb8 --- /dev/null +++ b/selling/page/crm_funnel/crm_funnel.py @@ -0,0 +1,33 @@ +# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. +# License: GNU General Public License v3. See license.txt + +from __future__ import unicode_literals +import webnotes + +@webnotes.whitelist() +def get_funnel_data(from_date, to_date): + active_leads = webnotes.conn.sql("""select count(*) from `tabLead` + where (`modified` between %s and %s) + and status != "Do Not Contact" """, (from_date, to_date))[0][0] + + active_leads += webnotes.conn.sql("""select count(distinct customer) from `tabContact` + where (`modified` between %s and %s) + and status != "Passive" """, (from_date, to_date))[0][0] + + opportunities = webnotes.conn.sql("""select count(*) from `tabOpportunity` + where docstatus = 1 and (`modified` between %s and %s) + and status != "Lost" """, (from_date, to_date))[0][0] + + quotations = webnotes.conn.sql("""select count(*) from `tabQuotation` + where docstatus = 1 and (`modified` between %s and %s) + and status != "Lost" """, (from_date, to_date))[0][0] + + sales_orders = webnotes.conn.sql("""select count(*) from `tabQuotation` + where docstatus = 1 and (`modified` between %s and %s)""", (from_date, to_date))[0][0] + + return [ + { "title": "Active Leads / Customers", "value": active_leads, "color": "#B03B46" }, + { "title": "Opportunities", "value": opportunities, "color": "#F09C00" }, + { "title": "Quotations", "value": quotations, "color": "#006685" }, + { "title": "Sales Orders", "value": sales_orders, "color": "#00AD65" } + ] diff --git a/selling/page/crm_funnel/crm_funnel.txt b/selling/page/crm_funnel/crm_funnel.txt new file mode 100644 index 00000000000..29cf566053b --- /dev/null +++ b/selling/page/crm_funnel/crm_funnel.txt @@ -0,0 +1,33 @@ +[ + { + "creation": "2013-10-04 13:17:18", + "docstatus": 0, + "modified": "2013-10-04 13:17:18", + "modified_by": "Administrator", + "owner": "Administrator" + }, + { + "doctype": "Page", + "icon": "icon-filter", + "module": "Selling", + "name": "__common__", + "page_name": "crm-funnel", + "standard": "Yes", + "title": "CRM Funnel" + }, + { + "doctype": "Page Role", + "name": "__common__", + "parent": "crm-funnel", + "parentfield": "roles", + "parenttype": "Page", + "role": "Sales Manager" + }, + { + "doctype": "Page", + "name": "crm-funnel" + }, + { + "doctype": "Page Role" + } +] \ No newline at end of file From a42d32f4c58777f644b9e9e0f26def2f76a16045 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A1rbara=20Perretti?= Date: Fri, 4 Oct 2013 14:07:56 -0300 Subject: [PATCH 095/200] Fix translate selling_home.js --- selling/page/selling_home/selling_home.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/selling/page/selling_home/selling_home.js b/selling/page/selling_home/selling_home.js index cd8eb7225d5..b4e93054ccd 100644 --- a/selling/page/selling_home/selling_home.js +++ b/selling/page/selling_home/selling_home.js @@ -63,7 +63,7 @@ wn.module_page["Selling"] = [ "label": wn._("Selling Settings"), "route": "Form/Selling Settings", "doctype":"Selling Settings", - "description": wn.("Settings for Selling Module") + "description": wn._("Settings for Selling Module") }, { "route":"Form/Shopping Cart Settings", From e47cc0408cac50d01ad25728d505296ed6efceb0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A1rbara=20Perretti?= Date: Fri, 4 Oct 2013 15:06:55 -0300 Subject: [PATCH 096/200] Fix translate bom.js --- manufacturing/doctype/bom/bom.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/manufacturing/doctype/bom/bom.js b/manufacturing/doctype/bom/bom.js index badb108048a..020325867a1 100644 --- a/manufacturing/doctype/bom/bom.js +++ b/manufacturing/doctype/bom/bom.js @@ -6,7 +6,7 @@ cur_frm.cscript.refresh = function(doc,dt,dn){ cur_frm.toggle_enable("item", doc.__islocal); if (!doc.__islocal && doc.docstatus<2) { - cur_frm.add_custom_button("Update Cost", cur_frm.cscript.update_cost); + cur_frm.add_custom_button(wn._("Update Cost"), cur_frm.cscript.update_cost); } cur_frm.cscript.with_operations(doc); @@ -123,7 +123,7 @@ cur_frm.cscript.qty = function(doc, cdt, cdn) { cur_frm.cscript.rate = function(doc, cdt, cdn) { var d = locals[cdt][cdn]; if (d.bom_no) { - msgprint("You can not change rate if BOM mentioned agianst any item"); + msgprint(wn._("You can not change rate if BOM mentioned agianst any item")); get_bom_material_detail(doc, cdt, cdn); } else { calculate_rm_cost(doc); From e582ac4eea09caed23742e66bbe3f68c7519a5a0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A1rbara=20Perretti?= Date: Fri, 4 Oct 2013 15:09:54 -0300 Subject: [PATCH 097/200] Fix translate production_order.js --- .../doctype/production_order/production_order.js | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/manufacturing/doctype/production_order/production_order.js b/manufacturing/doctype/production_order/production_order.js index f680776a565..7c4325dc37d 100644 --- a/manufacturing/doctype/production_order/production_order.js +++ b/manufacturing/doctype/production_order/production_order.js @@ -13,7 +13,7 @@ cur_frm.cscript.refresh = function(doc, dt, dn) { cfn_set_fields(doc, dt, dn); if(doc.docstatus===0 && !doc.__islocal) { - cur_frm.set_intro("Submit this Production Order for further processing."); + cur_frm.set_intro(wn._("Submit this Production Order for further processing.")); } else if(doc.docstatus===1) { var percent = flt(doc.produced_qty) / flt(doc.qty) * 100; cur_frm.dashboard.add_progress(cint(percent) + "% " + wn._("Complete"), percent); @@ -27,13 +27,13 @@ cur_frm.cscript.refresh = function(doc, dt, dn) { var cfn_set_fields = function(doc, dt, dn) { if (doc.docstatus == 1) { if (doc.status != 'Stopped' && doc.status != 'Completed') - cur_frm.add_custom_button('Stop!', cur_frm.cscript['Stop Production Order']); + cur_frm.add_custom_button(wn._('Stop!'), cur_frm.cscript['Stop Production Order']); else if (doc.status == 'Stopped') - cur_frm.add_custom_button('Unstop', cur_frm.cscript['Unstop Production Order']); + cur_frm.add_custom_button(wn._('Unstop'), cur_frm.cscript['Unstop Production Order']); if (doc.status == 'Submitted' || doc.status == 'Material Transferred' || doc.status == 'In Process'){ - cur_frm.add_custom_button('Transfer Raw Materials', cur_frm.cscript['Transfer Raw Materials']); - cur_frm.add_custom_button('Update Finished Goods', cur_frm.cscript['Update Finished Goods']); + cur_frm.add_custom_button(wn._('Transfer Raw Materials'), cur_frm.cscript['Transfer Raw Materials']); + cur_frm.add_custom_button(wn._('Update Finished Goods'), cur_frm.cscript['Update Finished Goods']); } } } @@ -47,7 +47,7 @@ cur_frm.cscript.production_item = function(doc) { cur_frm.cscript['Stop Production Order'] = function() { var doc = cur_frm.doc; - var check = confirm("Do you really want to stop production order: " + doc.name); + var check = confirm(wn._("Do you really want to stop production order: " + doc.name)); if (check) { return $c_obj(make_doclist(doc.doctype, doc.name), 'stop_unstop', 'Stopped', function(r, rt) {cur_frm.refresh();}); } @@ -55,7 +55,7 @@ cur_frm.cscript['Stop Production Order'] = function() { cur_frm.cscript['Unstop Production Order'] = function() { var doc = cur_frm.doc; - var check = confirm("Do really want to unstop production order: " + doc.name); + var check = confirm(wn._("Do really want to unstop production order: " + doc.name)); if (check) return $c_obj(make_doclist(doc.doctype, doc.name), 'stop_unstop', 'Unstopped', function(r, rt) {cur_frm.refresh();}); } @@ -105,5 +105,5 @@ cur_frm.set_query("bom_no", function(doc) { query:"controllers.queries.bom", filters: {item: cstr(doc.production_item)} } - } else msgprint(" Please enter Production Item first"); + } else msgprint(wn._("Please enter Production Item first")); }); \ No newline at end of file From 328f384cdc69f4226f84a7488497b2ad3ffc9ea7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A1rbara=20Perretti?= Date: Fri, 4 Oct 2013 15:11:58 -0300 Subject: [PATCH 098/200] Fix translate production_planning_tool.js --- .../production_planning_tool/production_planning_tool.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/manufacturing/doctype/production_planning_tool/production_planning_tool.js b/manufacturing/doctype/production_planning_tool/production_planning_tool.js index daa701352b2..22bf6caef49 100644 --- a/manufacturing/doctype/production_planning_tool/production_planning_tool.js +++ b/manufacturing/doctype/production_planning_tool/production_planning_tool.js @@ -44,7 +44,7 @@ cur_frm.fields_dict['pp_details'].grid.get_field('bom_no').get_query = function( query:"controllers.queries.bom", filters:{'item': cstr(d.item_code)} } - } else msgprint(" Please enter Item first"); + } else msgprint(wn._("Please enter Item first")); } cur_frm.fields_dict.customer.get_query = function(doc,cdt,cdn) { From 247ae8c6e53497ae1b0d15aafc6b805c168d24d6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A1rbara=20Perretti?= Date: Fri, 4 Oct 2013 15:24:42 -0300 Subject: [PATCH 099/200] Fix translate customer_issue.js --- support/doctype/customer_issue/customer_issue.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/support/doctype/customer_issue/customer_issue.js b/support/doctype/customer_issue/customer_issue.js index 5b670d452c2..d161a78a780 100644 --- a/support/doctype/customer_issue/customer_issue.js +++ b/support/doctype/customer_issue/customer_issue.js @@ -6,7 +6,7 @@ wn.provide("erpnext.support"); erpnext.support.CustomerIssue = wn.ui.form.Controller.extend({ refresh: function() { if((cur_frm.doc.status=='Open' || cur_frm.doc.status == 'Work In Progress')) { - cur_frm.add_custom_button('Make Maintenance Visit', this.make_maintenance_visit) + cur_frm.add_custom_button(wn._('Make Maintenance Visit'), this.make_maintenance_visit) } }, From 1fcc3d9748fdcbaa31c158c01bd93c889d57ed84 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A1rbara=20Perretti?= Date: Fri, 4 Oct 2013 15:32:05 -0300 Subject: [PATCH 100/200] Fix translate maintenance_schedule.js --- support/doctype/maintenance_schedule/maintenance_schedule.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/support/doctype/maintenance_schedule/maintenance_schedule.js b/support/doctype/maintenance_schedule/maintenance_schedule.js index 6b693435ab4..bdcdd3d935a 100644 --- a/support/doctype/maintenance_schedule/maintenance_schedule.js +++ b/support/doctype/maintenance_schedule/maintenance_schedule.js @@ -91,7 +91,7 @@ cur_frm.cscript.periodicity = function(doc, cdt, cdn){ return get_server_fields('get_no_of_visits',docstring(arg),'item_maintenance_detail',doc, cdt, cdn, 1); } else{ - msgprint("Please enter Start Date and End Date"); + msgprint(wn._("Please enter Start Date and End Date")); } } @@ -103,7 +103,7 @@ cur_frm.cscript.generate_schedule = function(doc, cdt, cdn) { } ); } else { - alert("Please save the document before generating maintenance schedule"); + alert(wn._("Please save the document before generating maintenance schedule")); } } From cd855901225045659c939bd0609d600ffd0162d8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A1rbara=20Perretti?= Date: Fri, 4 Oct 2013 15:37:27 -0300 Subject: [PATCH 101/200] Fix translate newsletter.js --- support/doctype/newsletter/newsletter.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/support/doctype/newsletter/newsletter.js b/support/doctype/newsletter/newsletter.js index 05311963cb9..b532b299bbc 100644 --- a/support/doctype/newsletter/newsletter.js +++ b/support/doctype/newsletter/newsletter.js @@ -16,7 +16,7 @@ cur_frm.cscript.refresh = function(doc) { erpnext.hide_naming_series(); if(!doc.__islocal && !cint(doc.email_sent) && !doc.__unsaved && inList(wn.boot.profile.can_write, doc.doctype)) { - cur_frm.add_custom_button('Send', function() { + cur_frm.add_custom_button(wn._('Send'), function() { return $c_obj(make_doclist(doc.doctype, doc.name), 'send_emails', '', function(r) { cur_frm.refresh(); }); From f889c4e59c906d0b0c7192d041c42c9e6e36941b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A1rbara=20Perretti?= Date: Fri, 4 Oct 2013 15:44:04 -0300 Subject: [PATCH 102/200] Fix translate support_ticket.js --- support/doctype/support_ticket/support_ticket.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/support/doctype/support_ticket/support_ticket.js b/support/doctype/support_ticket/support_ticket.js index 0e612734393..8e34a89c540 100644 --- a/support/doctype/support_ticket/support_ticket.js +++ b/support/doctype/support_ticket/support_ticket.js @@ -23,8 +23,8 @@ $.extend(cur_frm.cscript, new erpnext.support.CustomerIssue({frm: cur_frm})); $.extend(cur_frm.cscript, { onload: function(doc, dt, dn) { if(in_list(user_roles,'System Manager')) { - cur_frm.footer.help_area.innerHTML = '

    Email Settings
    \ - Integrate incoming support emails to Support Ticket

    '; + cur_frm.footer.help_area.innerHTML = '

    '+wn._("Email Settings")+'
    \ + '+wn._("Integrate incoming support emails to Support Ticket")+'

    '; } }, From 19165f8f86be868c05ea50ad333e32760711e9cb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A1rbara=20Perretti?= Date: Fri, 4 Oct 2013 15:51:17 -0300 Subject: [PATCH 103/200] Fix translate support_analytics.js --- .../support_analytics/support_analytics.js | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/support/page/support_analytics/support_analytics.js b/support/page/support_analytics/support_analytics.js index 7e449178a68..ecc07496241 100644 --- a/support/page/support_analytics/support_analytics.js +++ b/support/page/support_analytics/support_analytics.js @@ -4,7 +4,7 @@ wn.pages['support-analytics'].onload = function(wrapper) { wn.ui.make_app_page({ parent: wrapper, - title: 'Support Analytics', + title: wn._('Support Analytics'), single_column: true }); @@ -18,7 +18,7 @@ wn.pages['support-analytics'].onload = function(wrapper) { erpnext.SupportAnalytics = wn.views.GridReportWithPlot.extend({ init: function(wrapper) { this._super({ - title: "Support Analtyics", + title: wn._("Support Analtyics"), page: wrapper, parent: $(wrapper).find('.layout-main'), appframe: wrapper.appframe, @@ -27,22 +27,22 @@ erpnext.SupportAnalytics = wn.views.GridReportWithPlot.extend({ }, filters: [ - {fieldtype:"Select", label: "Fiscal Year", link:"Fiscal Year", + {fieldtype:"Select", label: wn._("Fiscal Year"), link:"Fiscal Year", default_value: "Select Fiscal Year..."}, - {fieldtype:"Date", label: "From Date"}, - {fieldtype:"Label", label: "To"}, - {fieldtype:"Date", label: "To Date"}, - {fieldtype:"Select", label: "Range", + {fieldtype:"Date", label: wn._("From Date")}, + {fieldtype:"Label", label: wn._("To")}, + {fieldtype:"Date", label: wn._("To Date")}, + {fieldtype:"Select", label: wn._("Range"), options:["Daily", "Weekly", "Monthly", "Quarterly", "Yearly"]}, - {fieldtype:"Button", label: "Refresh", icon:"icon-refresh icon-white", cssClass:"btn-info"}, - {fieldtype:"Button", label: "Reset Filters"} + {fieldtype:"Button", label: wn._("Refresh"), icon:"icon-refresh icon-white", cssClass:"btn-info"}, + {fieldtype:"Button", label: wn._("Reset Filters")} ], setup_columns: function() { var std_columns = [ - {id: "check", name: "Plot", field: "check", width: 30, + {id: "check", name: wn._("Plot"), field: "check", width: 30, formatter: this.check_formatter}, - {id: "status", name: "Status", field: "status", width: 100}, + {id: "status", name: wn._("Status"), field: "status", width: 100}, ]; this.make_date_range_columns(); this.columns = std_columns.concat(this.columns); From fdb1fd361dd74bee28d81f62b36a4558cf644eb4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A1rbara=20Perretti?= Date: Fri, 4 Oct 2013 17:23:24 -0300 Subject: [PATCH 104/200] Fix translate company.js --- setup/doctype/company/company.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/setup/doctype/company/company.js b/setup/doctype/company/company.js index ca3c93b49bf..2f1d6624f4c 100644 --- a/setup/doctype/company/company.js +++ b/setup/doctype/company/company.js @@ -22,7 +22,8 @@ cur_frm.cscript.has_special_chars = function(t) { cur_frm.cscript.company_name = function(doc){ if(doc.company_name && cur_frm.cscript.has_special_chars(doc.company_name)){ - msgprint("Special Characters ! @ # $ % ^ * + = - [ ] ' ; , / { } | : < > ? are not allowed for\nCompany Name " + doc.company_name +"") + msgprint((""+wn._("Special Characters")+" ! @ # $ % ^ * + = - [ ] ' ; , / { } | : < > ? "+ + wn._("are not allowed for ")+"\n"+wn._("Company Name")+" "+ doc.company_name +"")) doc.company_name = ''; refresh_field('company_name'); } @@ -30,7 +31,8 @@ cur_frm.cscript.company_name = function(doc){ cur_frm.cscript.abbr = function(doc){ if(doc.abbr && cur_frm.cscript.has_special_chars(doc.abbr)){ - msgprint("Special Characters ! @ # $ % ^ * + = - [ ] ' ; , / { } | : < > ? are not allowed for\nAbbr " + doc.abbr +"") + msgprint(""wn._("Special Characters ")+"! @ # $ % ^ * + = - [ ] ' ; , / { } | : < > ?" + + wn._("are not allowed for")+ "\nAbbr " + doc.abbr +"") doc.abbr = ''; refresh_field('abbr'); } From 6e2fc5c67617fa1987b59756aca91c1efeb98a4f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A1rbara=20Perretti?= Date: Fri, 4 Oct 2013 17:31:15 -0300 Subject: [PATCH 105/200] Fix translate customer_group.js --- setup/doctype/customer_group/customer_group.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup/doctype/customer_group/customer_group.js b/setup/doctype/customer_group/customer_group.js index 2953de542d5..9541cf8e106 100644 --- a/setup/doctype/customer_group/customer_group.js +++ b/setup/doctype/customer_group/customer_group.js @@ -9,7 +9,7 @@ cur_frm.cscript.set_root_readonly = function(doc) { // read-only for root customer group if(!doc.parent_customer_group) { cur_frm.perm = [[1,0,0], [1,0,0]]; - cur_frm.set_intro("This is a root customer group and cannot be edited."); + cur_frm.set_intro(wn._("This is a root customer group and cannot be edited.")); } else { cur_frm.set_intro(null); } From bd16f133ced2d49708bf501160090eb6fd478850 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A1rbara=20Perretti?= Date: Fri, 4 Oct 2013 17:34:45 -0300 Subject: [PATCH 106/200] Fix translate email_digest.js --- setup/doctype/email_digest/email_digest.js | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/setup/doctype/email_digest/email_digest.js b/setup/doctype/email_digest/email_digest.js index 552109231fb..d009080e98b 100644 --- a/setup/doctype/email_digest/email_digest.js +++ b/setup/doctype/email_digest/email_digest.js @@ -3,10 +3,10 @@ cur_frm.cscript.refresh = function(doc, dt, dn) { doc = locals[dt][dn]; - var save_msg = "You must Save the form before proceeding"; - var err_msg = "There was an error. One probable reason could be that you haven't saved the form. Please contact support@erpnext.com if the problem persists." + var save_msg = wn._("You must ")+ ""+wn._("Save ")+""+wn._("the form before proceeding"); + var err_msg = wn._("There was an error. One probable reason could be that you haven't saved the form. Please contact support@erpnext.com if the problem persists.") - cur_frm.add_custom_button('View Now', function() { + cur_frm.add_custom_button(wn._('View Now'), function() { doc = locals[dt][dn]; if(doc.__unsaved != 1) { return $c_obj(make_doclist(dt, dn), 'get_digest_msg', '', function(r, rt) { @@ -16,7 +16,7 @@ cur_frm.cscript.refresh = function(doc, dt, dn) { } else { //console.log(arguments); var d = new wn.ui.Dialog({ - title: 'Email Digest: ' + dn, + title: wn._('Email Digest: ') + dn, width: 800 }); @@ -29,7 +29,7 @@ cur_frm.cscript.refresh = function(doc, dt, dn) { msgprint(save_msg); } }, 1); - cur_frm.add_custom_button('Send Now', function() { + cur_frm.add_custom_button(wn._('Send Now'), function() { doc = locals[dt][dn]; if(doc.__unsaved != 1) { return $c_obj(make_doclist(dt, dn), 'send', '', function(r, rt) { @@ -38,7 +38,7 @@ cur_frm.cscript.refresh = function(doc, dt, dn) { console.log(r.exc); } else { //console.log(arguments); - msgprint('Message Sent'); + msgprint(wn._('Message Sent')); } }); } else { @@ -56,7 +56,7 @@ cur_frm.cscript.addremove_recipients = function(doc, dt, dn) { // Open a dialog and display checkboxes against email addresses doc = locals[dt][dn]; var d = new wn.ui.Dialog({ - title: 'Add/Remove Recipients', + title: wn._('Add/Remove Recipients'), width: 400 }); var dialog_div = $a(d.body, 'div', 'dialog-div', '', ''); From cc58f86842244f2c3dbdaa40570a00f7aa956238 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A1rbara=20Perretti?= Date: Fri, 4 Oct 2013 17:37:30 -0300 Subject: [PATCH 107/200] Fix translate item_group.js --- setup/doctype/item_group/item_group.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/setup/doctype/item_group/item_group.js b/setup/doctype/item_group/item_group.js index 31edef27dec..c5a08d4daee 100644 --- a/setup/doctype/item_group/item_group.js +++ b/setup/doctype/item_group/item_group.js @@ -4,7 +4,7 @@ cur_frm.cscript.refresh = function(doc, cdt, cdn) { cur_frm.cscript.set_root_readonly(doc); - cur_frm.add_custom_button("Item Group Tree", function() { + cur_frm.add_custom_button(wn._("Item Group Tree"), function() { wn.set_route("Sales Browser", "Item Group"); }) } @@ -13,7 +13,7 @@ cur_frm.cscript.set_root_readonly = function(doc) { // read-only for root item group if(!doc.parent_item_group) { cur_frm.perm = [[1,0,0], [1,0,0]]; - cur_frm.set_intro("This is a root item group and cannot be edited."); + cur_frm.set_intro(wn._("This is a root item group and cannot be edited.")); } else { cur_frm.set_intro(null); } From 5cf2c004724038c61dd4f87041b71ed1ab0919a7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A1rbara=20Perretti?= Date: Fri, 4 Oct 2013 17:40:44 -0300 Subject: [PATCH 108/200] Fix translate sales_partner.js --- setup/doctype/sales_partner/sales_partner.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/setup/doctype/sales_partner/sales_partner.js b/setup/doctype/sales_partner/sales_partner.js index 86b77121421..351aa3d0f68 100644 --- a/setup/doctype/sales_partner/sales_partner.js +++ b/setup/doctype/sales_partner/sales_partner.js @@ -39,7 +39,7 @@ cur_frm.cscript.make_address = function() { return "select name, address_type, address_line1, address_line2, city, state, country, pincode, fax, email_id, phone, is_primary_address, is_shipping_address from tabAddress where sales_partner='"+cur_frm.docname+"' and docstatus != 2 order by is_primary_address desc" }, as_dict: 1, - no_results_message: 'No addresses created', + no_results_message: wn._('No addresses created'), render_row: function(wrapper, data) { $(wrapper).css('padding','5px 0px'); var link = $ln(wrapper,cstr(data.name), function() { loaddoc("Address", this.dn); }, {fontWeight:'bold'}); @@ -69,7 +69,7 @@ cur_frm.cscript.make_contact = function() { return "select name, first_name, last_name, email_id, phone, mobile_no, department, designation, is_primary_contact from tabContact where sales_partner='"+cur_frm.docname+"' and docstatus != 2 order by is_primary_contact desc" }, as_dict: 1, - no_results_message: 'No contacts created', + no_results_message: wn._('No contacts created'), render_row: function(wrapper, data) { $(wrapper).css('padding', '5px 0px'); var link = $ln(wrapper, cstr(data.name), function() { loaddoc("Contact", this.dn); }, {fontWeight:'bold'}); From cd0a40b20f327513a557658b2b6498d51d86b91e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A1rbara=20Perretti?= Date: Fri, 4 Oct 2013 17:41:33 -0300 Subject: [PATCH 109/200] Fix translate sales_person.js --- setup/doctype/sales_person/sales_person.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup/doctype/sales_person/sales_person.js b/setup/doctype/sales_person/sales_person.js index 34f267e825d..ec21ead6be6 100644 --- a/setup/doctype/sales_person/sales_person.js +++ b/setup/doctype/sales_person/sales_person.js @@ -9,7 +9,7 @@ cur_frm.cscript.set_root_readonly = function(doc) { // read-only for root if(!doc.parent_sales_person) { cur_frm.perm = [[1,0,0], [1,0,0]]; - cur_frm.set_intro("This is a root sales person and cannot be edited."); + cur_frm.set_intro(wn._("This is a root sales person and cannot be edited.")); } else { cur_frm.set_intro(null); } From 988096e82d6888544a4703a3f2ff65b4f790a08c Mon Sep 17 00:00:00 2001 From: Anand Doshi Date: Mon, 7 Oct 2013 18:06:52 +0530 Subject: [PATCH 110/200] [feature] Sales Funnel visualization. Go to Selling > Analytics > Sales Funnel --- .../{crm_funnel => sales_funnel}/__init__.py | 0 .../sales_funnel.css} | 0 .../sales_funnel.js} | 29 ++++++++++++++----- .../sales_funnel.py} | 0 .../sales_funnel.txt} | 8 ++--- selling/page/selling_home/selling_home.js | 4 +++ 6 files changed, 29 insertions(+), 12 deletions(-) rename selling/page/{crm_funnel => sales_funnel}/__init__.py (100%) rename selling/page/{crm_funnel/crm_funnel.css => sales_funnel/sales_funnel.css} (100%) rename selling/page/{crm_funnel/crm_funnel.js => sales_funnel/sales_funnel.js} (83%) rename selling/page/{crm_funnel/crm_funnel.py => sales_funnel/sales_funnel.py} (100%) rename selling/page/{crm_funnel/crm_funnel.txt => sales_funnel/sales_funnel.txt} (81%) diff --git a/selling/page/crm_funnel/__init__.py b/selling/page/sales_funnel/__init__.py similarity index 100% rename from selling/page/crm_funnel/__init__.py rename to selling/page/sales_funnel/__init__.py diff --git a/selling/page/crm_funnel/crm_funnel.css b/selling/page/sales_funnel/sales_funnel.css similarity index 100% rename from selling/page/crm_funnel/crm_funnel.css rename to selling/page/sales_funnel/sales_funnel.css diff --git a/selling/page/crm_funnel/crm_funnel.js b/selling/page/sales_funnel/sales_funnel.js similarity index 83% rename from selling/page/crm_funnel/crm_funnel.js rename to selling/page/sales_funnel/sales_funnel.js index a2d2b934790..e2c3a98bf59 100644 --- a/selling/page/crm_funnel/crm_funnel.js +++ b/selling/page/sales_funnel/sales_funnel.js @@ -1,14 +1,18 @@ // Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. // License: GNU General Public License v3. See license.txt -wn.pages['crm-funnel'].onload = function(wrapper) { +wn.pages['sales-funnel'].onload = function(wrapper) { wn.ui.make_app_page({ parent: wrapper, - title: 'CRM Funnel', + title: 'Sales Funnel', single_column: true }); wrapper.crm_funnel = new erpnext.CRMFunnel(wrapper); + + wrapper.appframe.add_module_icon("Selling", "sales-funnel", function() { + wn.set_route("selling-home"); + }); } erpnext.CRMFunnel = Class.extend({ @@ -40,8 +44,8 @@ erpnext.CRMFunnel = Class.extend({ .appendTo(this.elements.layout); this.options = { - from_date: wn.datetime.get_today(), - to_date: wn.datetime.add_months(wn.datetime.get_today(), -1) + from_date: wn.datetime.add_months(wn.datetime.get_today(), -1), + to_date: wn.datetime.get_today() }; // set defaults and bind on change @@ -108,7 +112,7 @@ erpnext.CRMFunnel = Class.extend({ y_old = y; // new y - y = y + (me.options.height * d.value / me.options.total_value); + y = y + d.height; // new x var half_side = (me.options.height - y) / Math.sqrt(3); @@ -122,15 +126,24 @@ erpnext.CRMFunnel = Class.extend({ }, prepare: function() { + var me = this; + this.elements.no_data.toggle(false); // calculate width and height options this.options.width = $(this.elements.funnel_wrapper).width() * 2.0 / 3.0; this.options.height = (Math.sqrt(3) * this.options.width) / 2.0; - // calculate total value - this.options.total_value = this.options.data.reduce( - function(prev, curr) { return prev + curr.value; }, 0.0); + // calculate total weightage + // as height decreases, area decreases by the square of the reduction + // hence, compensating by squaring the index value + this.options.total_weightage = this.options.data.reduce( + function(prev, curr, i) { return prev + Math.pow(i+1, 2) * curr.value; }, 0.0); + + // calculate height for each data + $.each(this.options.data, function(i, d) { + d.height = me.options.height * d.value * Math.pow(i+1, 2) / me.options.total_weightage; + }); this.elements.canvas = $('') .appendTo(this.elements.funnel_wrapper.empty()) diff --git a/selling/page/crm_funnel/crm_funnel.py b/selling/page/sales_funnel/sales_funnel.py similarity index 100% rename from selling/page/crm_funnel/crm_funnel.py rename to selling/page/sales_funnel/sales_funnel.py diff --git a/selling/page/crm_funnel/crm_funnel.txt b/selling/page/sales_funnel/sales_funnel.txt similarity index 81% rename from selling/page/crm_funnel/crm_funnel.txt rename to selling/page/sales_funnel/sales_funnel.txt index 29cf566053b..b841f20fdcc 100644 --- a/selling/page/crm_funnel/crm_funnel.txt +++ b/selling/page/sales_funnel/sales_funnel.txt @@ -11,21 +11,21 @@ "icon": "icon-filter", "module": "Selling", "name": "__common__", - "page_name": "crm-funnel", + "page_name": "sales-funnel", "standard": "Yes", - "title": "CRM Funnel" + "title": "Sales Funnel" }, { "doctype": "Page Role", "name": "__common__", - "parent": "crm-funnel", + "parent": "sales-funnel", "parentfield": "roles", "parenttype": "Page", "role": "Sales Manager" }, { "doctype": "Page", - "name": "crm-funnel" + "name": "sales-funnel" }, { "doctype": "Page Role" diff --git a/selling/page/selling_home/selling_home.js b/selling/page/selling_home/selling_home.js index 9697ccf9855..5dd33e640f4 100644 --- a/selling/page/selling_home/selling_home.js +++ b/selling/page/selling_home/selling_home.js @@ -155,6 +155,10 @@ wn.module_page["Selling"] = [ "label":wn._("Sales Analytics"), page: "sales-analytics" }, + { + "label":wn._("Sales Funnel"), + page: "sales-funnel" + }, ] }, { From 8941841a9c289ff43e725e7eaca3c9371f7af369 Mon Sep 17 00:00:00 2001 From: Rushabh Mehta Date: Mon, 7 Oct 2013 18:22:29 +0530 Subject: [PATCH 111/200] [setup wizard] added more steps [minor] [wip] --- public/js/utils.js | 2 +- setup/page/setup_wizard/setup_wizard.js | 141 +++++++++++++++++++----- 2 files changed, 113 insertions(+), 30 deletions(-) diff --git a/public/js/utils.js b/public/js/utils.js index 61e613bdecb..6879b69e7a1 100644 --- a/public/js/utils.js +++ b/public/js/utils.js @@ -20,7 +20,7 @@ $.extend(erpnext, { hide_company: function() { if(cur_frm.fields_dict.company) { - var companies = Object.keys(locals[":Company"]); + var companies = Object.keys(locals[":Company"] || {}); if(companies.length === 1) { if(!cur_frm.doc.company) cur_frm.set_value("company", companies[0]); cur_frm.toggle_display("company", false); diff --git a/setup/page/setup_wizard/setup_wizard.js b/setup/page/setup_wizard/setup_wizard.js index b88f6e6c13e..7ace2ef7bf7 100644 --- a/setup/page/setup_wizard/setup_wizard.js +++ b/setup/page/setup_wizard/setup_wizard.js @@ -1,14 +1,18 @@ wn.pages['setup-wizard'].onload = function(wrapper) { + $(".navbar:first").toggle(false); + erpnext.wiz = new wn.wiz.Wizard({ parent: wrapper, title: wn._("ERPNext Setup Guide"), slides: [ // User { - title: wn._("The First User"), + title: wn._("The First User: You"), + icon: "icon-user", fields: [ {"fieldname": "first_name", "label": wn._("First Name"), "fieldtype": "Data", reqd:1}, {"fieldname": "last_name", "label": wn._("Last Name"), "fieldtype": "Data", reqd:1}, + {fieldtype:"Attach Image", fieldname:"attach_profile", label:"Attach Your Profile..."}, ], help: wn._('The first user will become the System Manager (you can change that later).') }, @@ -16,6 +20,7 @@ wn.pages['setup-wizard'].onload = function(wrapper) { // Organization { title: wn._("The Organization"), + icon: "icon-building", fields: [ {fieldname:'company_name', label: wn._('Company Name'), fieldtype:'Data', reqd:1, placeholder: 'e.g. "My Company LLC"'}, @@ -37,6 +42,7 @@ wn.pages['setup-wizard'].onload = function(wrapper) { // Country { title: wn._("Country, Timezone and Currency"), + icon: "icon-flag", fields: [ {fieldname:'country', label: wn._('Country'), reqd:1, options: "", fieldtype: 'Select'}, @@ -81,48 +87,122 @@ wn.pages['setup-wizard'].onload = function(wrapper) { // Logo { + icon: "icon-bookmark", title: wn._("Logo and Letter Heads"), help: wn._('Upload your letter head and logo - you can edit them later.'), - html: '

    ' + wn._('Upload Logo') + '


    ' - +'

    ' + wn._('Upload Letter Head') + '

    ', + fields: [ + {fieldtype:"Attach Image", fieldname:"attach_letterhead", label:"Attach Letterhead..."}, + {fieldtype:"Attach Image", fieldname:"attach_logo", label:"Attach Logo..."}, + ], + // html: '

    ' + wn._('Upload Logo') + '


    ' + // +'

    ' + wn._('Upload Letter Head') + '

    ', onload: function(slide) { - wn.upload.make({ - parent: slide.$wrapper.find(".upload-area-letter-head").css({"margin-left": "10px"}), - on_attach: function(fileobj) { - console.log(fileobj); - } - }); - - wn.upload.make({ - parent: slide.$wrapper.find(".upload-area-logo").css({"margin-left": "10px"}), - on_attach: function(fileobj) { - console.log(fileobj); - } - }); + // wn.upload.make({ + // parent: slide.$wrapper.find(".upload-area-letter-head").css({"margin-left": "10px"}), + // on_attach: function(fileobj) { + // console.log(fileobj); + // } + // }); + // + // wn.upload.make({ + // parent: slide.$wrapper.find(".upload-area-logo").css({"margin-left": "10px"}), + // on_attach: function(fileobj) { + // console.log(fileobj); + // } + // }); } }, // Taxes { + icon: "icon-money", "title": wn._("Add Taxes"), "help": wn._("List your tax heads (e.g. VAT, Excise) (upto 3) and their standard rates. This will create a standard template, you can edit and add more later."), "fields": [ + {fieldtype:"Column Break", fieldname:"cb_1", "label": "Tax Heads"}, {fieldtype:"Data", fieldname:"tax_1", label:"Tax 1", placeholder:"e.g. VAT"}, - {fieldtype:"Data", fieldname:"tax_rate_1", label:"Rate for Tax 1 (%)", placeholder:"e.g. 5"}, {fieldtype:"Data", fieldname:"tax_2", label:"Tax 2", placeholder:"e.g. Customs Duty"}, - {fieldtype:"Data", fieldname:"tax_rate_2", label:"Rate for Tax 2 (%)", placeholder:"e.g. 5"}, {fieldtype:"Data", fieldname:"tax_3", label:"Tax 3", placeholder:"e.g. Excise"}, - {fieldtype:"Data", fieldname:"tax_rate_3", label:"Rate for Tax 3 (%)", placeholder:"e.g. 5"}, + {fieldtype:"Column Break", fieldname:"cb_2", "label": "Tax Rates"}, + {fieldtype:"Data", fieldname:"tax_rate_1", label:"Rate (%)", placeholder:"e.g. 5"}, + {fieldtype:"Data", fieldname:"tax_rate_2", label:"Rate (%)", placeholder:"e.g. 5"}, + {fieldtype:"Data", fieldname:"tax_rate_3", label:"Rate (%)", placeholder:"e.g. 5"}, + ], + onload: function(slide) { + } + }, + + // Items to Sell + { + icon: "icon-barcode", + "title": wn._("Your Products or Services"), + "help": wn._("List your products or services that you sell to your customers."), + "fields": [ + {fieldtype:"Data", fieldname:"item_1", label:"Item 1", placeholder:"A Product or Service"}, + {fieldtype:"Data", fieldname:"item_2", label:"Item 2", placeholder:"A Product or Service"}, + {fieldtype:"Data", fieldname:"item_3", label:"Item 3", placeholder:"A Product or Service"}, + {fieldtype:"Data", fieldname:"item_4", label:"Item 4", placeholder:"A Product or Service"}, + {fieldtype:"Data", fieldname:"item_5", label:"Item 5", placeholder:"A Product or Service"}, + {fieldtype:"Column Break", fieldname:"cb_2", "label": "Attachments"}, + {fieldtype:"Attach", fieldname:"item_img_1", label:"Attach Image..."}, + {fieldtype:"Attach", fieldname:"item_img_2", label:"Attach Image..."}, + {fieldtype:"Attach", fieldname:"item_img_3", label:"Attach Image..."}, + {fieldtype:"Attach", fieldname:"item_img_4", label:"Attach Image..."}, + {fieldtype:"Attach", fieldname:"item_img_5", label:"Attach Image..."}, + ], + onload: function(slide) { + } + }, + + // Items to Buy + { + icon: "icon-barcode", + "title": wn._("Products or Services You Buy"), + "help": wn._("List a few products or services you buy from your suppliers or vendors. If these are same as your products, then do not add them."), + "fields": [ + {fieldtype:"Data", fieldname:"item_buy_1", label:"Item 1", placeholder:"A Product or Service"}, + {fieldtype:"Data", fieldname:"item_buy_2", label:"Item 2", placeholder:"A Product or Service"}, + {fieldtype:"Data", fieldname:"item_buy_3", label:"Item 3", placeholder:"A Product or Service"}, + {fieldtype:"Data", fieldname:"item_buy_4", label:"Item 4", placeholder:"A Product or Service"}, + {fieldtype:"Data", fieldname:"item_buy_5", label:"Item 5", placeholder:"A Product or Service"}, + ], + onload: function(slide) { + } + }, + + // Customers + { + icon: "icon-group", + "title": wn._("Your Customers"), + "help": wn._("List a few of your customers. They could be organizations or individuals."), + "fields": [ + {fieldtype:"Data", fieldname:"customer_1", label:"Customer 1", placeholder:"Customer Name"}, + {fieldtype:"Data", fieldname:"customer_2", label:"Customer 2", placeholder:"Customer Name"}, + {fieldtype:"Data", fieldname:"customer_3", label:"Customer 3", placeholder:"Customer Name"}, + {fieldtype:"Data", fieldname:"customer_4", label:"Customer 4", placeholder:"Customer Name"}, + {fieldtype:"Data", fieldname:"customer_5", label:"Customer 5", placeholder:"Customer Name"}, + ], + onload: function(slide) { + } + }, + + // Suppliers + { + icon: "icon-group", + "title": wn._("Your Suppliers"), + "help": wn._("List a few of your suppliers. They could be organizations or individuals."), + "fields": [ + {fieldtype:"Data", fieldname:"supplier_1", label:"Supplier 1", placeholder:"Supplier Name"}, + {fieldtype:"Data", fieldname:"supplier_2", label:"Supplier 2", placeholder:"Supplier Name"}, + {fieldtype:"Data", fieldname:"supplier_3", label:"Supplier 3", placeholder:"Supplier Name"}, + {fieldtype:"Data", fieldname:"supplier_4", label:"Supplier 4", placeholder:"Supplier Name"}, + {fieldtype:"Data", fieldname:"supplier_5", label:"Supplier 5", placeholder:"Supplier Name"}, ], onload: function(slide) { - slide.form.fields_dict.tax_rate_1.$wrapper.css("margin-left", "50%"); - slide.form.fields_dict.tax_rate_2.$wrapper.css("margin-left", "50%"); - slide.form.fields_dict.tax_rate_3.$wrapper.css("margin-left", "50%"); } } - - // + ] }) @@ -163,20 +243,22 @@ wn.wiz.WizardSlide = Class.extend({ }, make: function() { var me = this; - this.$wrapper = $(repl('
    \ -
    %(main_title)s: %(title)s
    \ + this.$wrapper = $(repl('
    \ +
    %(main_title)s: Step %(step)s
    \
    \
    \
    \
    \ +

    %(title)s


    \
    \
    \ -

    %(title)s

    %(help)s

    \ +

    %(help)s

    \
    \
    \ \
    \ -
    ', {help:this.help, title:this.title, main_title:this.wiz.title, width: (flt(this.id + 1) / this.wiz.slides.length) * 100})) +
    ', {help:this.help, title:this.title, main_title:this.wiz.title, step: this.id + 1, + width: (flt(this.id + 1) / (this.wiz.slides.length+1)) * 100, icon:this.icon})) .appendTo(this.wiz.parent); this.body = this.$wrapper.find(".form")[0]; @@ -184,7 +266,8 @@ wn.wiz.WizardSlide = Class.extend({ if(this.fields) { this.form = new wn.ui.FieldGroup({ fields: this.fields, - body: this.body + body: this.body, + no_submit_on_enter: true }); this.form.make(); } else { From 8e65dae35cf700797baa240f83a82ee6d6914ea5 Mon Sep 17 00:00:00 2001 From: Anand Doshi Date: Mon, 7 Oct 2013 19:25:50 +0530 Subject: [PATCH 112/200] [minor] [cleanup] add roles in setup control --- setup/doctype/setup_control/setup_control.py | 41 +++++++------------- 1 file changed, 15 insertions(+), 26 deletions(-) diff --git a/setup/doctype/setup_control/setup_control.py b/setup/doctype/setup_control/setup_control.py index b78bfcc7d6e..76818f0b4d7 100644 --- a/setup/doctype/setup_control/setup_control.py +++ b/setup/doctype/setup_control/setup_control.py @@ -4,17 +4,16 @@ from __future__ import unicode_literals import webnotes -from webnotes.utils import cint, cstr, getdate, now, nowdate, get_defaults -from webnotes.model.doc import Document, addchild -from webnotes.model.code import get_obj -from webnotes import session, form, msgprint +from webnotes.utils import cint, cstr, getdate, nowdate, get_defaults +from webnotes.model.doc import Document +from webnotes import msgprint class DocType: def __init__(self, d, dl): self.doc, self.doclist = d, dl def setup_account(self, args): - import webnotes, json + import json if isinstance(args, basestring): args = json.loads(args) webnotes.conn.begin() @@ -175,7 +174,6 @@ class DocType: system_managers = get_system_managers() if not system_managers: return - from webnotes.model.doc import Document for company in companies_list: if company and company[0]: edigest = webnotes.bean({ @@ -216,28 +214,19 @@ class DocType: abbr = cstr(curr_year)[-2:] + '-' + cstr(curr_year+1)[-2:] return fy, stdt, abbr - def create_profile(self, user_email, user_fname, user_lname, pwd=None): - pr = Document('Profile') - pr.first_name = user_fname - pr.last_name = user_lname - pr.name = pr.email = user_email - pr.enabled = 1 - pr.save(1) - if pwd: - webnotes.conn.sql("""insert into __Auth (user, `password`) - values (%s, password(%s)) - on duplicate key update `password`=password(%s)""", - (user_email, pwd, pwd)) - - add_all_roles_to(pr.name) - -def add_all_roles_to(name): - profile = webnotes.doc("Profile", name) +def add_all_roles_to(profile): + if isinstance(profile, basestring): + profile = webnotes.bean("Profile", profile) + for role in webnotes.conn.sql("""select name from tabRole"""): if role[0] not in ["Administrator", "Guest", "All", "Customer", "Supplier", "Partner"]: - d = profile.addchild("user_roles", "UserRole") - d.role = role[0] - d.insert() + profile.doclist.append({ + "doctype": "UserRole", + "parentfield": "user_roles", + "role": role[0] + }) + + profile.save() def create_territories(): """create two default territories, one for home country and one named Rest of the World""" From f6a6399763dd3a9892783ced2a8b29ddbdf54a3e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A1rbara=20Perretti?= Date: Mon, 7 Oct 2013 14:06:23 -0300 Subject: [PATCH 113/200] Fix translate home/page/activity/activity.js --- home/page/activity/activity.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/home/page/activity/activity.js b/home/page/activity/activity.js index 8d451939cc7..edfe50f363b 100644 --- a/home/page/activity/activity.js +++ b/home/page/activity/activity.js @@ -4,7 +4,7 @@ wn.pages['activity'].onload = function(wrapper) { wn.ui.make_app_page({ parent: wrapper, - title: "Activity", + title: wn._("Activity"), single_column: true }) wrapper.appframe.add_module_icon("Activity"); @@ -21,7 +21,7 @@ wn.pages['activity'].onload = function(wrapper) { // Build Report Button if(wn.boot.profile.can_get_report.indexOf("Feed")!=-1) { - wrapper.appframe.add_button('Build Report', function() { + wrapper.appframe.add_button(wn._('Build Report'), function() { wn.set_route('Report', "Feed"); }, 'icon-th') } From ab5fe0756a3c2a598cfa82a2c6227ce65137f1b8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A1rbara=20Perretti?= Date: Mon, 7 Oct 2013 14:24:49 -0300 Subject: [PATCH 114/200] Fix translate latest_updates.js --- home/page/latest_updates/latest_updates.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/home/page/latest_updates/latest_updates.js b/home/page/latest_updates/latest_updates.js index 094eeb558e0..d5e361eb767 100644 --- a/home/page/latest_updates/latest_updates.js +++ b/home/page/latest_updates/latest_updates.js @@ -4,7 +4,7 @@ wn.pages['latest-updates'].onload = function(wrapper) { wn.ui.make_app_page({ parent: wrapper, - title: 'Latest Updates', + title: wn._('Latest Updates'), single_column: true }); @@ -16,9 +16,9 @@ wn.pages['latest-updates'].onload = function(wrapper) { method:"home.page.latest_updates.latest_updates.get", callback: function(r) { parent.empty(); - $("

    Report issues at\ - GitHub Issues

    \ -

    Commit Log

    ") + $("

    "+wn._("Report issues at")+ + ""+wn._("GitHub Issues")+"

    \ +

    "+wn._("Commit Log")+"

    ") .appendTo(parent); var $tbody = $('
    ') From c5f211332569800604ad68255504e3df2710553d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A1rbara=20Perretti?= Date: Mon, 7 Oct 2013 15:13:29 -0300 Subject: [PATCH 115/200] Fix translate appraisal.js --- hr/doctype/appraisal/appraisal.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hr/doctype/appraisal/appraisal.js b/hr/doctype/appraisal/appraisal.js index f94a288fd52..8c5df8e2971 100644 --- a/hr/doctype/appraisal/appraisal.js +++ b/hr/doctype/appraisal/appraisal.js @@ -45,7 +45,7 @@ cur_frm.cscript.score = function(doc,cdt,cdn){ var d = locals[cdt][cdn]; if (d.score){ if (flt(d.score) > 5) { - msgprint("Score must be less than or equal to 5"); + msgprint(wn._("Score must be less than or equal to 5")); d.score = 0; refresh_field('score', d.name, 'appraisal_details'); } From 63439ef7c7da9e39a1d5ef9479cda0b719bcd827 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A1rbara=20Perretti?= Date: Mon, 7 Oct 2013 15:33:56 -0300 Subject: [PATCH 116/200] fix translate hr/doctype/employee/employee.js --- hr/doctype/employee/employee.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hr/doctype/employee/employee.js b/hr/doctype/employee/employee.js index 01200e7d22c..cfedfc61112 100644 --- a/hr/doctype/employee/employee.js +++ b/hr/doctype/employee/employee.js @@ -21,7 +21,7 @@ erpnext.hr.EmployeeController = wn.ui.form.Controller.extend({ var me = this; erpnext.hide_naming_series(); if(!this.frm.doc.__islocal) { - cur_frm.add_custom_button('Make Salary Structure', function() { + cur_frm.add_custom_button(wn._('Make Salary Structure'), function() { me.make_salary_structure(this); }); } }, From 28181d338499d1a264884a4af9ba8b1120171ee3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A1rbara=20Perretti?= Date: Mon, 7 Oct 2013 15:39:20 -0300 Subject: [PATCH 117/200] Fix translate expense_claim.js --- hr/doctype/expense_claim/expense_claim.js | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/hr/doctype/expense_claim/expense_claim.js b/hr/doctype/expense_claim/expense_claim.js index f7895b10eb0..e19cac77512 100644 --- a/hr/doctype/expense_claim/expense_claim.js +++ b/hr/doctype/expense_claim/expense_claim.js @@ -93,28 +93,28 @@ cur_frm.cscript.refresh = function(doc,cdt,cdn){ cur_frm.savesubmit(); if(doc.docstatus==1 && wn.model.can_create("Journal Voucher")) - cur_frm.add_custom_button("Make Bank Voucher", cur_frm.cscript.make_bank_voucher); + cur_frm.add_custom_button(wn._("Make Bank Voucher"), cur_frm.cscript.make_bank_voucher); } } cur_frm.cscript.set_help = function(doc) { cur_frm.set_intro(""); if(doc.__islocal && !in_list(user_roles, "HR User")) { - cur_frm.set_intro("Fill the form and save it") + cur_frm.set_intro(wn._("Fill the form and save it")) } else { if(doc.docstatus==0 && doc.approval_status=="Draft") { if(user==doc.exp_approver) { - cur_frm.set_intro("You are the Expense Approver for this record. \ - Please Update the 'Status' and Save"); + cur_frm.set_intro(wn._("You are the Expense Approver for this record. \ + Please Update the 'Status' and Save")); } else { - cur_frm.set_intro("Expense Claim is pending approval. \ - Only the Expense Approver can update status."); + cur_frm.set_intro(wn._("Expense Claim is pending approval. \ + Only the Expense Approver can update status.")); } } else { if(doc.approval_status=="Approved") { - cur_frm.set_intro("Expense Claim has been approved."); + cur_frm.set_intro(wn._("Expense Claim has been approved.")); } else if(doc.approval_status=="Rejected") { - cur_frm.set_intro("Expense Claim has been rejected."); + cur_frm.set_intro(wn._("Expense Claim has been rejected.")); } } } From f70e3aabcb3b6b10a191aa101886a69b736c7661 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A1rbara=20Perretti?= Date: Mon, 7 Oct 2013 16:22:21 -0300 Subject: [PATCH 118/200] Fix translate hr/doctype/leave_application/leave_application.js --- hr/doctype/leave_application/leave_application.js | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/hr/doctype/leave_application/leave_application.js b/hr/doctype/leave_application/leave_application.js index 5969f4dc4fb..7b32cff6919 100755 --- a/hr/doctype/leave_application/leave_application.js +++ b/hr/doctype/leave_application/leave_application.js @@ -31,14 +31,14 @@ cur_frm.cscript.refresh = function(doc, dt, dn) { } cur_frm.set_intro(""); if(doc.__islocal && !in_list(user_roles, "HR User")) { - cur_frm.set_intro("Fill the form and save it") + cur_frm.set_intro(wn._("Fill the form and save it")) } else { if(doc.docstatus==0 && doc.status=="Open") { if(user==doc.leave_approver) { - cur_frm.set_intro("You are the Leave Approver for this record. Please Update the 'Status' and Save"); + cur_frm.set_intro(wn._("You are the Leave Approver for this record. Please Update the 'Status' and Save")); cur_frm.toggle_enable("status", true); } else { - cur_frm.set_intro("This Leave Application is pending approval. Only the Leave Apporver can update status.") + cur_frm.set_intro(wn._("This Leave Application is pending approval. Only the Leave Apporver can update status.")) cur_frm.toggle_enable("status", false); if(!doc.__islocal) { if(cur_frm.frm_head.appframe.buttons.Submit) @@ -47,12 +47,12 @@ cur_frm.cscript.refresh = function(doc, dt, dn) { } } else { if(doc.status=="Approved") { - cur_frm.set_intro("Leave application has been approved."); + cur_frm.set_intro(wn._("Leave application has been approved.")); if(cur_frm.doc.docstatus==0) { - cur_frm.set_intro("Please submit to update Leave Balance."); + cur_frm.set_intro(wn._("Please submit to update Leave Balance.")); } } else if(doc.status=="Rejected") { - cur_frm.set_intro("Leave application has been rejected."); + cur_frm.set_intro(wn._("Leave application has been rejected.")); } } } @@ -86,7 +86,7 @@ cur_frm.cscript.from_date = function(doc, dt, dn) { cur_frm.cscript.to_date = function(doc, dt, dn) { if(cint(doc.half_day) == 1 && cstr(doc.from_date) && doc.from_date != doc.to_date){ - msgprint("To Date should be same as From Date for Half Day leave"); + msgprint(wn._("To Date should be same as From Date for Half Day leave")); set_multiple(dt,dn,{to_date:doc.from_date}); } cur_frm.cscript.calculate_total_days(doc, dt, dn); From 2521910d56887a2edbfa79b1639a8180bb823b54 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A1rbara=20Perretti?= Date: Mon, 7 Oct 2013 16:24:17 -0300 Subject: [PATCH 119/200] Fix translate leave_control_panel.js --- hr/doctype/leave_control_panel/leave_control_panel.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hr/doctype/leave_control_panel/leave_control_panel.js b/hr/doctype/leave_control_panel/leave_control_panel.js index a53f031f4c7..7a840ba78d5 100644 --- a/hr/doctype/leave_control_panel/leave_control_panel.js +++ b/hr/doctype/leave_control_panel/leave_control_panel.js @@ -15,7 +15,7 @@ cur_frm.cscript.to_date = function(doc, cdt, cdn) { function(r, rt) { var doc = locals[cdt][cdn]; if (r.message) { - alert("To date cannot be before from date"); + alert(wn._("To date cannot be before from date")); doc.to_date = ''; refresh_field('to_date'); } From e9548a55e99c619146f7b1028d071c2cdae62ee1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A1rbara=20Perretti?= Date: Mon, 7 Oct 2013 16:27:46 -0300 Subject: [PATCH 120/200] Fix translate salary_manager.js --- hr/doctype/salary_manager/salary_manager.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/hr/doctype/salary_manager/salary_manager.js b/hr/doctype/salary_manager/salary_manager.js index 178ab3ef6b9..b27d41c418b 100644 --- a/hr/doctype/salary_manager/salary_manager.js +++ b/hr/doctype/salary_manager/salary_manager.js @@ -5,7 +5,7 @@ var display_activity_log = function(msg) { if(!pscript.ss_html) pscript.ss_html = $a(cur_frm.fields_dict['activity_log'].wrapper,'div'); pscript.ss_html.innerHTML = - '
    Activity Log:
    '+msg+'
    '; + '
    '+wn._("Activity Log:")+'
    '+msg+'
    '; } //Create salary slip @@ -23,7 +23,7 @@ cur_frm.cscript.create_salary_slip = function(doc, cdt, cdn) { //Submit salary slip //----------------------- 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(wn._("Do you really want to Submit all Salary Slip for month : ") + doc.month+ wn._(" and fiscal year : ")+doc.fiscal_year); if(check){ var callback = function(r, rt){ if (r.message) @@ -49,7 +49,7 @@ cur_frm.cscript.make_jv = function(doc, dt, dn) { var jv = wn.model.make_new_doc_and_get_name('Journal Voucher'); jv = locals['Journal Voucher'][jv]; jv.voucher_type = 'Bank Voucher'; - jv.user_remark = 'Payment of salary for the month: ' + doc.month + 'and fiscal year: ' + doc.fiscal_year; + jv.user_remark = wn._('Payment of salary for the month: ') + doc.month + wn._('and fiscal year: ') + doc.fiscal_year; jv.fiscal_year = doc.fiscal_year; jv.company = doc.company; jv.posting_date = dateutil.obj_to_str(new Date()); From 5fa2fca9bda76f814101ba38a2c89d8c56abf322 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A1rbara=20Perretti?= Date: Mon, 7 Oct 2013 16:31:36 -0300 Subject: [PATCH 121/200] fix translate salary_structure.js --- hr/doctype/salary_structure/salary_structure.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hr/doctype/salary_structure/salary_structure.js b/hr/doctype/salary_structure/salary_structure.js index 81cb63d352d..15b35129353 100644 --- a/hr/doctype/salary_structure/salary_structure.js +++ b/hr/doctype/salary_structure/salary_structure.js @@ -12,7 +12,7 @@ cur_frm.cscript.onload = function(doc, dt, dn){ cur_frm.cscript.refresh = function(doc, dt, dn){ if((!doc.__islocal) && (doc.is_active == 'Yes')){ - cur_frm.add_custom_button('Make Salary Slip', cur_frm.cscript['Make Salary Slip']); + cur_frm.add_custom_button(wn._('Make Salary Slip'), cur_frm.cscript['Make Salary Slip']); } cur_frm.toggle_enable('employee', doc.__islocal); From 6287e8e906a9fc62b050e6c0c9aa4f73d0bdf7cb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A1rbara=20Perretti?= Date: Mon, 7 Oct 2013 16:34:30 -0300 Subject: [PATCH 122/200] Fix translate upload_attendance.js --- hr/doctype/upload_attendance/upload_attendance.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/hr/doctype/upload_attendance/upload_attendance.js b/hr/doctype/upload_attendance/upload_attendance.js index 71e266928db..bf584a00fc9 100644 --- a/hr/doctype/upload_attendance/upload_attendance.js +++ b/hr/doctype/upload_attendance/upload_attendance.js @@ -17,7 +17,7 @@ erpnext.hr.AttendanceControlPanel = wn.ui.form.Controller.extend({ get_template:function() { if(!this.frm.doc.att_fr_date || !this.frm.doc.att_to_date) { - msgprint("Attendance From Date and Attendance To Date is mandatory"); + msgprint(wn._("Attendance From Date and Attendance To Date is mandatory")); return; } window.location.href = repl(wn.request.url + @@ -56,10 +56,10 @@ erpnext.hr.AttendanceControlPanel = wn.ui.form.Controller.extend({ return v; }); - r.messages = ["

    Import Failed!

    "] + r.messages = ["

    "+wn._("Import Failed!"+"

    "] .concat(r.messages) } else { - r.messages = ["

    Import Successful!

    "]. + r.messages = ["

    "+wn._("Import Successful!"+"

    "]. concat(r.message.messages) } From d851a0426186890fbd974988fa2c218926b2af43 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A1rbara=20Perretti?= Date: Mon, 7 Oct 2013 16:36:29 -0300 Subject: [PATCH 123/200] Fix translate employee_birthday.js --- hr/report/employee_birthday/employee_birthday.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/hr/report/employee_birthday/employee_birthday.js b/hr/report/employee_birthday/employee_birthday.js index 3fd849266f1..8fce812abf5 100644 --- a/hr/report/employee_birthday/employee_birthday.js +++ b/hr/report/employee_birthday/employee_birthday.js @@ -5,7 +5,7 @@ wn.query_reports["Employee Birthday"] = { "filters": [ { "fieldname":"month", - "label": "Month", + "label": wn._("Month"), "fieldtype": "Select", "options": "Jan\nFeb\nMar\nApr\nMay\nJun\nJul\nAug\nSep\nOct\nNov\nDec", "default": ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", @@ -13,7 +13,7 @@ wn.query_reports["Employee Birthday"] = { }, { "fieldname":"company", - "label": "Company", + "label": wn._("Company"), "fieldtype": "Link", "options": "Company", "default": wn.defaults.get_user_default("company") From 54e8fbc070378c7b86929ab4b9cfb6d63d99f6be Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A1rbara=20Perretti?= Date: Mon, 7 Oct 2013 16:37:21 -0300 Subject: [PATCH 124/200] Fix translate employee_leave_balance.js --- hr/report/employee_leave_balance/employee_leave_balance.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/hr/report/employee_leave_balance/employee_leave_balance.js b/hr/report/employee_leave_balance/employee_leave_balance.js index 1bf252d2a7a..7af65b641f0 100644 --- a/hr/report/employee_leave_balance/employee_leave_balance.js +++ b/hr/report/employee_leave_balance/employee_leave_balance.js @@ -5,14 +5,14 @@ wn.query_reports["Employee Leave Balance"] = { "filters": [ { "fieldname":"fiscal_year", - "label": "Fiscal Year", + "label": wn._("Fiscal Year"), "fieldtype": "Link", "options": "Fiscal Year", "default": wn.defaults.get_user_default("fiscal_year") }, { "fieldname":"company", - "label": "Company", + "label": wn._("Company"), "fieldtype": "Link", "options": "Company", "default": wn.defaults.get_user_default("company") From 3b956d98b8c8c21c9bf2689e5f5096c0faeffc29 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A1rbara=20Perretti?= Date: Mon, 7 Oct 2013 16:38:35 -0300 Subject: [PATCH 125/200] Fix translate monthly_attendance_sheet.js --- .../monthly_attendance_sheet/monthly_attendance_sheet.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/hr/report/monthly_attendance_sheet/monthly_attendance_sheet.js b/hr/report/monthly_attendance_sheet/monthly_attendance_sheet.js index 678e7af713b..fc14b6dd8ee 100644 --- a/hr/report/monthly_attendance_sheet/monthly_attendance_sheet.js +++ b/hr/report/monthly_attendance_sheet/monthly_attendance_sheet.js @@ -5,7 +5,7 @@ wn.query_reports["Monthly Attendance Sheet"] = { "filters": [ { "fieldname":"month", - "label": "Month", + "label": wn._("Month"), "fieldtype": "Select", "options": "Jan\nFeb\nMar\nApr\nMay\nJun\nJul\nAug\nSep\nOct\nNov\nDec", "default": ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", @@ -13,20 +13,20 @@ wn.query_reports["Monthly Attendance Sheet"] = { }, { "fieldname":"fiscal_year", - "label": "Fiscal Year", + "label": wn._("Fiscal Year"), "fieldtype": "Link", "options": "Fiscal Year", "default": sys_defaults.fiscal_year, }, { "fieldname":"employee", - "label": "Employee", + "label": wn._("Employee"), "fieldtype": "Link", "options": "Employee" }, { "fieldname":"company", - "label": "Company", + "label": wn._("Company"), "fieldtype": "Link", "options": "Company", "default": wn.defaults.get_default("company") From a82d51b5667200c5d01da09629685cca4eb4d144 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A1rbara=20Perretti?= Date: Mon, 7 Oct 2013 16:39:41 -0300 Subject: [PATCH 126/200] Fix translate monthly_salary_register.js --- .../monthly_salary_register/monthly_salary_register.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/hr/report/monthly_salary_register/monthly_salary_register.js b/hr/report/monthly_salary_register/monthly_salary_register.js index eb33d08cd0f..45d7ff9bad9 100644 --- a/hr/report/monthly_salary_register/monthly_salary_register.js +++ b/hr/report/monthly_salary_register/monthly_salary_register.js @@ -5,7 +5,7 @@ wn.query_reports["Monthly Salary Register"] = { "filters": [ { "fieldname":"month", - "label": "Month", + "label": wn._("Month"), "fieldtype": "Select", "options": "Jan\nFeb\nMar\nApr\nMay\nJun\nJul\nAug\nSep\nOct\nNov\nDec", "default": ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", @@ -13,20 +13,20 @@ wn.query_reports["Monthly Salary Register"] = { }, { "fieldname":"fiscal_year", - "label": "Fiscal Year", + "label": wn._("Fiscal Year"), "fieldtype": "Link", "options": "Fiscal Year", "default": sys_defaults.fiscal_year, }, { "fieldname":"employee", - "label": "Employee", + "label": wn._("Employee"), "fieldtype": "Link", "options": "Employee" }, { "fieldname":"company", - "label": "Company", + "label": wn._("Company"), "fieldtype": "Link", "options": "Company", "default": wn.defaults.get_default("company") From 4de55b4f6efd8ab6b29f5dc8e0b497c31a2da6f2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A1rbara=20Perretti?= Date: Mon, 7 Oct 2013 17:10:04 -0300 Subject: [PATCH 127/200] Fix translate account_tree_grid.js --- public/js/account_tree_grid.js | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/public/js/account_tree_grid.js b/public/js/account_tree_grid.js index c779cfa6d92..28db1d79461 100644 --- a/public/js/account_tree_grid.js +++ b/public/js/account_tree_grid.js @@ -36,39 +36,39 @@ erpnext.AccountTreeGrid = wn.views.TreeGridReport.extend({ }, setup_columns: function() { this.columns = [ - {id: "name", name: "Account", field: "name", width: 300, cssClass: "cell-title", + {id: "name", name: wn._("Account"), field: "name", width: 300, cssClass: "cell-title", formatter: this.tree_formatter}, - {id: "opening_debit", name: "Opening (Dr)", field: "opening_debit", width: 100, + {id: "opening_debit", name: wn._("Opening (Dr)"), field: "opening_debit", width: 100, formatter: this.currency_formatter}, - {id: "opening_credit", name: "Opening (Cr)", field: "opening_credit", width: 100, + {id: "opening_credit", name: wn._("Opening (Cr)"), field: "opening_credit", width: 100, formatter: this.currency_formatter}, - {id: "debit", name: "Debit", field: "debit", width: 100, + {id: "debit", name: wn._("Debit"), field: "debit", width: 100, formatter: this.currency_formatter}, - {id: "credit", name: "Credit", field: "credit", width: 100, + {id: "credit", name: wn._("Credit"), field: "credit", width: 100, formatter: this.currency_formatter}, - {id: "closing_debit", name: "Closing (Dr)", field: "closing_debit", width: 100, + {id: "closing_debit", name: wn._("Closing (Dr)"), field: "closing_debit", width: 100, formatter: this.currency_formatter}, - {id: "closing_credit", name: "Closing (Cr)", field: "closing_credit", width: 100, + {id: "closing_credit", name: wn._("Closing (Cr)"), field: "closing_credit", width: 100, formatter: this.currency_formatter} ]; }, filters: [ - {fieldtype: "Select", label: "Company", link:"Company", default_value: "Select Company...", + {fieldtype: "Select", label: wn._("Company"), link:"Company", default_value: "Select Company...", filter: function(val, item, opts, me) { if (item.company == val || val == opts.default_value) { return me.apply_zero_filter(val, item, opts, me); } return false; }}, - {fieldtype: "Select", label: "Fiscal Year", link:"Fiscal Year", + {fieldtype: "Select", label: wn._("Fiscal Year"), link:"Fiscal Year", default_value: "Select Fiscal Year..."}, - {fieldtype: "Date", label: "From Date"}, - {fieldtype: "Label", label: "To"}, - {fieldtype: "Date", label: "To Date"}, - {fieldtype: "Button", label: "Refresh", icon:"icon-refresh icon-white", + {fieldtype: "Date", label: wn._("From Date")}, + {fieldtype: "Label", label: wn._("To")}, + {fieldtype: "Date", label: wn._("To Date")}, + {fieldtype: "Button", label: wn._("Refresh"), icon:"icon-refresh icon-white", cssClass:"btn-info"}, - {fieldtype: "Button", label: "Reset Filters"}, + {fieldtype: "Button", label: wn._("Reset Filters")}, ], setup_filters: function() { this._super(); @@ -193,7 +193,7 @@ erpnext.AccountTreeGrid = wn.views.TreeGridReport.extend({ set_fiscal_year: function() { if (this.opening_date > this.closing_date) { - msgprint("Opening Date should be before Closing Date"); + msgprint(wn._("Opening Date should be before Closing Date")); return; } @@ -207,7 +207,7 @@ erpnext.AccountTreeGrid = wn.views.TreeGridReport.extend({ }); if (!this.fiscal_year) { - msgprint("Opening Date and Closing Date should be within same Fiscal Year"); + msgprint(wn._("Opening Date and Closing Date should be within same Fiscal Year")); return; } }, From f48ae145944387bf2f22d53489e9bcc6114dae74 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A1rbara=20Perretti?= Date: Mon, 7 Oct 2013 17:27:37 -0300 Subject: [PATCH 128/200] Fix translate complete_setup.js --- public/js/complete_setup.js | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/public/js/complete_setup.js b/public/js/complete_setup.js index e565621a2ae..eeb39d60d59 100644 --- a/public/js/complete_setup.js +++ b/public/js/complete_setup.js @@ -15,24 +15,24 @@ $.extend(erpnext.complete_setup, { var d = new wn.ui.Dialog({ title: "Setup", fields: [ - {fieldname:'first_name', label:'Your First Name', fieldtype:'Data', reqd: 1}, - {fieldname:'last_name', label:'Your Last Name', fieldtype:'Data'}, - {fieldname:'company_name', label:'Company Name', fieldtype:'Data', reqd:1, - description: 'e.g. "My Company LLC"'}, - {fieldname:'company_abbr', label:'Company Abbreviation', fieldtype:'Data', - description:'e.g. "MC"',reqd:1}, - {fieldname:'fy_start', label:'Financial Year Start Date', fieldtype:'Select', - description:'Your financial year begins on"', reqd:1, + {fieldname:'first_name', label:wn._('Your First Name'), fieldtype:'Data', reqd: 1}, + {fieldname:'last_name', label: wn._('Your Last Name'), fieldtype:'Data'}, + {fieldname:'company_name', label:wn._('Company Name'), fieldtype:'Data', reqd:1, + description: wn._('e.g. "My Company LLC"')}, + {fieldname:'company_abbr', label:wn._('Company Abbreviation'), fieldtype:'Data', + description:wn._('e.g. "MC"'),reqd:1}, + {fieldname:'fy_start', label:wn._('Financial Year Start Date'), fieldtype:'Select', + description:wn._('Your financial year begins on"'), reqd:1, options: erpnext.complete_setup.fy_start_list.join('\n')}, - {fieldname:'country', label: 'Country', reqd:1, + {fieldname:'country', label: wn._('Country'), reqd:1, options: "", fieldtype: 'Select'}, - {fieldname:'currency', label: 'Default Currency', reqd:1, + {fieldname:'currency', label: wn._('Default Currency'), reqd:1, options: "", fieldtype: 'Select'}, - {fieldname:'timezone', label: 'Time Zone', reqd:1, + {fieldname:'timezone', label: wn._('Time Zone'), reqd:1, options: "", fieldtype: 'Select'}, - {fieldname:'industry', label: 'Industry', reqd:1, + {fieldname:'industry', label: wn._('Industry'), reqd:1, options: erpnext.complete_setup.domains.join('\n'), fieldtype: 'Select'}, - {fieldname:'update', label:'Setup',fieldtype:'Button'}, + {fieldname:'update', label:wn._('Setup'),fieldtype:'Button'}, ], }); From 97408254a2243586ba3feb90eab80b2a7eb91a45 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A1rbara=20Perretti?= Date: Mon, 7 Oct 2013 17:29:58 -0300 Subject: [PATCH 129/200] Fix translate conf.js --- public/js/conf.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/public/js/conf.js b/public/js/conf.js index 993d2ab800a..bc49f711a8b 100644 --- a/public/js/conf.js +++ b/public/js/conf.js @@ -24,14 +24,14 @@ $(document).bind('toolbar_setup', function() { wn.provide('wn.ui.misc'); wn.ui.misc.about = function() { if(!wn.ui.misc.about_dialog) { - var d = new wn.ui.Dialog({title:'About ERPNext'}) + var d = new wn.ui.Dialog({title: wn._('About ERPNext')}) $(d.body).html(repl("
    \ -

    ERPNext is an open-source web based ERP made by Web Notes Technologies Pvt Ltd.\ +

    "+wn._("ERPNext is an open-source web based ERP made by Web Notes Technologies Pvt Ltd.\ to provide an integrated tool to manage most processes in a small organization.\ - For more information about Web Notes, or to buy hosting servies, go to \ - https://erpnext.com.

    \ -

    To report an issue, go to GitHub Issues

    \ + For more information about Web Notes, or to buy hosting servies, go to ")+ + "https://erpnext.com.

    \ +

    "+wn._("To report an issue, go to ")+"GitHub Issues

    \
    \

    License: GNU General Public License Version 3

    \
    ", wn.app)); From f99085055df48dee578dd4da712df1cd6d3ca80a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A1rbara=20Perretti?= Date: Mon, 7 Oct 2013 17:32:29 -0300 Subject: [PATCH 130/200] Fix translate feature_setup.js --- public/js/feature_setup.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/public/js/feature_setup.js b/public/js/feature_setup.js index 31f81be342c..96dea90eadb 100644 --- a/public/js/feature_setup.js +++ b/public/js/feature_setup.js @@ -198,7 +198,7 @@ $(document).bind('form_refresh', function() { } else if(cur_frm.fields_dict[fort]) { cur_frm.fields_dict[fort].grid.set_column_disp(pscript.feature_dict[sys_feat][cur_frm.doc.doctype][fort], false); } else { - msgprint('Grid "'+fort+'" does not exists'); + msgprint(wn._('Grid "')+fort+wn._('" does not exists')); } } } From 339129b21be69633f18ac778eac27f6990d3a9d2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A1rbara=20Perretti?= Date: Mon, 7 Oct 2013 17:54:05 -0300 Subject: [PATCH 131/200] Fix translate feature_setup.js --- public/js/feature_setup.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/public/js/feature_setup.js b/public/js/feature_setup.js index 96dea90eadb..0abb495994d 100644 --- a/public/js/feature_setup.js +++ b/public/js/feature_setup.js @@ -198,7 +198,7 @@ $(document).bind('form_refresh', function() { } else if(cur_frm.fields_dict[fort]) { cur_frm.fields_dict[fort].grid.set_column_disp(pscript.feature_dict[sys_feat][cur_frm.doc.doctype][fort], false); } else { - msgprint(wn._('Grid "')+fort+wn._('" does not exists')); + msgprint(wn._('Grid "')+fort+wn._('"does not exists')); } } } From 79c43988b43eadd224b51163d44289f657169618 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A1rbara=20Perretti?= Date: Mon, 7 Oct 2013 18:56:56 -0300 Subject: [PATCH 132/200] Fix translate feature_setup.js --- public/js/feature_setup.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/public/js/feature_setup.js b/public/js/feature_setup.js index 0abb495994d..96dea90eadb 100644 --- a/public/js/feature_setup.js +++ b/public/js/feature_setup.js @@ -198,7 +198,7 @@ $(document).bind('form_refresh', function() { } else if(cur_frm.fields_dict[fort]) { cur_frm.fields_dict[fort].grid.set_column_disp(pscript.feature_dict[sys_feat][cur_frm.doc.doctype][fort], false); } else { - msgprint(wn._('Grid "')+fort+wn._('"does not exists')); + msgprint(wn._('Grid "')+fort+wn._('" does not exists')); } } } From 8c5a5f1ed5bf6f54adc04d337d15011856c7dca5 Mon Sep 17 00:00:00 2001 From: Rushabh Mehta Date: Tue, 8 Oct 2013 17:59:11 +0530 Subject: [PATCH 133/200] New Setup Wizard --- .../june_2013/p08_shopping_cart_settings.py | 2 +- patches/patch_list.py | 1 + public/js/complete_setup.js | 126 ------- public/js/startup.js | 23 +- setup/doctype/company/company.txt | 4 +- setup/doctype/setup_control/README.md | 1 - setup/doctype/setup_control/__init__.py | 1 - setup/doctype/setup_control/setup_control.py | 255 ------------- setup/doctype/setup_control/setup_control.txt | 24 -- setup/page/setup_wizard/setup_wizard.js | 234 +++++++++--- setup/page/setup_wizard/setup_wizard.py | 349 ++++++++++++++++++ setup/page/setup_wizard/test_setup_data.py | 26 ++ setup/page/setup_wizard/test_setup_wizard.py | 14 + startup/install.py | 4 +- utilities/demo/make_demo.py | 3 +- utilities/doctype/contact/contact.txt | 6 +- 16 files changed, 589 insertions(+), 484 deletions(-) delete mode 100644 public/js/complete_setup.js delete mode 100644 setup/doctype/setup_control/README.md delete mode 100644 setup/doctype/setup_control/__init__.py delete mode 100644 setup/doctype/setup_control/setup_control.py delete mode 100644 setup/doctype/setup_control/setup_control.txt create mode 100644 setup/page/setup_wizard/setup_wizard.py create mode 100644 setup/page/setup_wizard/test_setup_data.py create mode 100644 setup/page/setup_wizard/test_setup_wizard.py diff --git a/patches/june_2013/p08_shopping_cart_settings.py b/patches/june_2013/p08_shopping_cart_settings.py index 479a6961e26..677b62a5e3e 100644 --- a/patches/june_2013/p08_shopping_cart_settings.py +++ b/patches/june_2013/p08_shopping_cart_settings.py @@ -7,7 +7,7 @@ def execute(): webnotes.reload_doc("selling", "doctype", "shopping_cart_settings") # create two default territories, one for home country and one named Rest of the World - from setup.doctype.setup_control.setup_control import create_territories + from setup.page.setup_wizard.setup_wizard import create_territories create_territories() webnotes.conn.set_value("Shopping Cart Settings", None, "default_territory", "Rest of the World") diff --git a/patches/patch_list.py b/patches/patch_list.py index 1596a2870b1..a5693854e5a 100644 --- a/patches/patch_list.py +++ b/patches/patch_list.py @@ -223,4 +223,5 @@ patch_list = [ "patches.october_2013.p01_update_delivery_note_prevdocs", "patches.october_2013.p02_set_communication_status", "patches.october_2013.p03_crm_update_status", + "execute:webnotes.delete_doc('DocType', 'Setup Control')", ] \ No newline at end of file diff --git a/public/js/complete_setup.js b/public/js/complete_setup.js deleted file mode 100644 index e565621a2ae..00000000000 --- a/public/js/complete_setup.js +++ /dev/null @@ -1,126 +0,0 @@ -// Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. -// License: GNU General Public License v3. See license.txt - -// complete my company registration -// -------------------------------- -wn.provide('erpnext.complete_setup'); - -$.extend(erpnext.complete_setup, { - show: function() { - d = erpnext.complete_setup.prepare_dialog(); - d.show(); - }, - - prepare_dialog: function() { - var d = new wn.ui.Dialog({ - title: "Setup", - fields: [ - {fieldname:'first_name', label:'Your First Name', fieldtype:'Data', reqd: 1}, - {fieldname:'last_name', label:'Your Last Name', fieldtype:'Data'}, - {fieldname:'company_name', label:'Company Name', fieldtype:'Data', reqd:1, - description: 'e.g. "My Company LLC"'}, - {fieldname:'company_abbr', label:'Company Abbreviation', fieldtype:'Data', - description:'e.g. "MC"',reqd:1}, - {fieldname:'fy_start', label:'Financial Year Start Date', fieldtype:'Select', - description:'Your financial year begins on"', reqd:1, - options: erpnext.complete_setup.fy_start_list.join('\n')}, - {fieldname:'country', label: 'Country', reqd:1, - options: "", fieldtype: 'Select'}, - {fieldname:'currency', label: 'Default Currency', reqd:1, - options: "", fieldtype: 'Select'}, - {fieldname:'timezone', label: 'Time Zone', reqd:1, - options: "", fieldtype: 'Select'}, - {fieldname:'industry', label: 'Industry', reqd:1, - options: erpnext.complete_setup.domains.join('\n'), fieldtype: 'Select'}, - {fieldname:'update', label:'Setup',fieldtype:'Button'}, - ], - }); - - if(user != 'Administrator'){ - d.$wrapper.find('.close').toggle(false); // Hide close image - $('header').toggle(false); // hide toolbar - } - - wn.call({ - method:"webnotes.country_info.get_country_timezone_info", - callback: function(data) { - erpnext.country_info = data.message.country_info; - erpnext.all_timezones = data.message.all_timezones; - d.get_input("country").empty() - .add_options([""].concat(keys(erpnext.country_info).sort())); - d.get_input("currency").empty() - .add_options(wn.utils.unique([""].concat($.map(erpnext.country_info, - function(opts, country) { return opts.currency; }))).sort()); - d.get_input("timezone").empty() - .add_options([""].concat(erpnext.all_timezones)); - } - }) - - // on clicking update - d.fields_dict.update.input.onclick = function() { - var data = d.get_values(); - if(!data) return; - $(this).set_working(); - return $c_obj('Setup Control','setup_account',data,function(r, rt){ - $(this).done_working(); - if(!r.exc) { - sys_defaults = r.message; - user_fullname = r.message.user_fullname; - wn.boot.user_info[user].fullname = user_fullname; - d.hide(); - $('header').toggle(true); - wn.container.wntoolbar.set_user_name(); - - setTimeout(function() { window.location.reload(); }, 3000); - } - }); - }; - - d.fields_dict.company_name.input.onchange = function() { - var parts = d.get_input("company_name").val().split(" "); - var abbr = $.map(parts, function(p) { return p ? p.substr(0,1) : null }).join(""); - d.get_input("company_abbr").val(abbr.toUpperCase()); - } - - d.fields_dict.country.input.onchange = function() { - var country = d.fields_dict.country.input.value; - var $timezone = $(d.fields_dict.timezone.input); - $timezone.empty(); - // add country specific timezones first - if(country){ - var timezone_list = erpnext.country_info[country].timezones || []; - $timezone.add_options(timezone_list.sort()); - - d.get_input("currency").val(erpnext.country_info[country].currency); - } - // add all timezones at the end, so that user has the option to change it to any timezone - $timezone.add_options([""].concat(erpnext.all_timezones)); - - }; - - // company name already set - if(wn.control_panel.company_name) { - var inp = d.fields_dict.company_name.input; - inp.value = wn.control_panel.company_name; - inp.disabled = true; - d.fields_dict.company_name.$input.trigger("change"); - } - - // set first name, last name - if(user_fullname) { - u = user_fullname.split(' '); - if(u[0]) { - d.fields_dict.first_name.input.value = u[0]; - } - if(u[1]) { - d.fields_dict.last_name.input.value = u[1]; - } - } - - return d; - }, - - fy_start_list: ['', '1st Jan', '1st Apr', '1st Jul', '1st Oct'], - - domains: ['', "Manufacturing", "Retail", "Distribution", "Services", "Other"], -}); \ No newline at end of file diff --git a/public/js/startup.js b/public/js/startup.js index eee8a056208..5a81d730a3a 100644 --- a/public/js/startup.js +++ b/public/js/startup.js @@ -9,25 +9,10 @@ erpnext.startup.start = function() { console.log('Starting up...'); $('#startup_div').html('Starting up...').toggle(true); - if(user != 'Guest'){ - // setup toolbar - erpnext.toolbar.setup(); - - // complete registration - if(in_list(user_roles,'System Manager') && (wn.boot.setup_complete==='No')) { - wn.require("app/js/complete_setup.js"); - erpnext.complete_setup.show(); - } else if(!wn.boot.customer_count) { - if(wn.get_route()[0]!=="Setup") { - msgprint("" - + wn._("Proceed to Setup") + "\ -

    "+ - wn._("This message goes away after you create your first customer.")+ - "

    ", wn._("Welcome")); - } - } else if(wn.boot.expires_on && in_list(user_roles, 'System Manager')) { - erpnext.startup.show_expiry_banner(); - } + erpnext.toolbar.setup(); + + if(wn.boot.expires_on && in_list(user_roles, 'System Manager')) { + erpnext.startup.show_expiry_banner(); } } diff --git a/setup/doctype/company/company.txt b/setup/doctype/company/company.txt index 1ba1dde4811..eb6b9ad35f4 100644 --- a/setup/doctype/company/company.txt +++ b/setup/doctype/company/company.txt @@ -2,7 +2,7 @@ { "creation": "2013-04-10 08:35:39", "docstatus": 0, - "modified": "2013-08-28 19:15:04", + "modified": "2013-10-08 15:18:34", "modified_by": "Administrator", "owner": "Administrator" }, @@ -80,7 +80,7 @@ "fieldtype": "Select", "label": "Domain", "options": "Distribution\nManufacturing\nRetail\nServices", - "reqd": 1 + "reqd": 0 }, { "doctype": "DocField", diff --git a/setup/doctype/setup_control/README.md b/setup/doctype/setup_control/README.md deleted file mode 100644 index 909fea49daf..00000000000 --- a/setup/doctype/setup_control/README.md +++ /dev/null @@ -1 +0,0 @@ -Account setup utility on first login. \ No newline at end of file diff --git a/setup/doctype/setup_control/__init__.py b/setup/doctype/setup_control/__init__.py deleted file mode 100644 index baffc488252..00000000000 --- a/setup/doctype/setup_control/__init__.py +++ /dev/null @@ -1 +0,0 @@ -from __future__ import unicode_literals diff --git a/setup/doctype/setup_control/setup_control.py b/setup/doctype/setup_control/setup_control.py deleted file mode 100644 index b78bfcc7d6e..00000000000 --- a/setup/doctype/setup_control/setup_control.py +++ /dev/null @@ -1,255 +0,0 @@ -# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. -# License: GNU General Public License v3. See license.txt - -from __future__ import unicode_literals -import webnotes - -from webnotes.utils import cint, cstr, getdate, now, nowdate, get_defaults -from webnotes.model.doc import Document, addchild -from webnotes.model.code import get_obj -from webnotes import session, form, msgprint - -class DocType: - def __init__(self, d, dl): - self.doc, self.doclist = d, dl - - def setup_account(self, args): - import webnotes, json - if isinstance(args, basestring): - args = json.loads(args) - webnotes.conn.begin() - - self.update_profile_name(args) - add_all_roles_to(webnotes.session.user) - self.create_fiscal_year_and_company(args) - self.set_defaults(args) - create_territories() - self.create_price_lists(args) - self.create_feed_and_todo() - self.create_email_digest() - - webnotes.clear_cache() - msgprint("Company setup is complete. This page will be refreshed in a moment.") - webnotes.conn.commit() - - return { - 'sys_defaults': get_defaults(), - 'user_fullname': (args.get('first_name') or '') + (args.get('last_name') - and (" " + args.get('last_name')) or '') - } - - def update_profile_name(self, args): - args['name'] = webnotes.session.get('user') - - # Update Profile - if not args.get('last_name') or args.get('last_name')=='None': args['last_name'] = None - webnotes.conn.sql("""\ - UPDATE `tabProfile` SET first_name=%(first_name)s, - last_name=%(last_name)s - WHERE name=%(name)s AND docstatus<2""", args) - - def create_fiscal_year_and_company(self, args): - curr_fiscal_year, fy_start_date, fy_abbr = self.get_fy_details(args.get('fy_start'), True) - webnotes.bean([{ - "doctype":"Fiscal Year", - 'year': curr_fiscal_year, - 'year_start_date': fy_start_date - }]).insert() - - curr_fiscal_year, fy_start_date, fy_abbr = self.get_fy_details(args.get('fy_start')) - webnotes.bean([{ - "doctype":"Fiscal Year", - 'year': curr_fiscal_year, - 'year_start_date': fy_start_date, - }]).insert() - - - # Company - webnotes.bean([{ - "doctype":"Company", - 'domain': args.get("industry"), - 'company_name':args.get('company_name'), - 'abbr':args.get('company_abbr'), - 'default_currency':args.get('currency'), - }]).insert() - - self.curr_fiscal_year = curr_fiscal_year - - def create_price_lists(self, args): - for pl_type in ["Selling", "Buying"]: - webnotes.bean([ - { - "doctype": "Price List", - "price_list_name": "Standard " + pl_type, - "buying_or_selling": pl_type, - "currency": args["currency"] - }, - { - "doctype": "For Territory", - "parentfield": "valid_for_territories", - "territory": "All Territories" - } - ]).insert() - - def set_defaults(self, args): - # enable default currency - webnotes.conn.set_value("Currency", args.get("currency"), "enabled", 1) - - global_defaults = webnotes.bean("Global Defaults", "Global Defaults") - global_defaults.doc.fields.update({ - 'current_fiscal_year': self.curr_fiscal_year, - 'default_currency': args.get('currency'), - 'default_company':args.get('company_name'), - 'date_format': webnotes.conn.get_value("Country", args.get("country"), "date_format"), - "float_precision": 4 - }) - global_defaults.save() - - accounts_settings = webnotes.bean("Accounts Settings") - accounts_settings.doc.auto_accounting_for_stock = 1 - accounts_settings.save() - - stock_settings = webnotes.bean("Stock Settings") - stock_settings.doc.item_naming_by = "Item Code" - stock_settings.doc.valuation_method = "FIFO" - stock_settings.doc.stock_uom = "Nos" - stock_settings.doc.auto_indent = 1 - stock_settings.save() - - selling_settings = webnotes.bean("Selling Settings") - selling_settings.doc.cust_master_name = "Customer Name" - selling_settings.doc.so_required = "No" - selling_settings.doc.dn_required = "No" - selling_settings.save() - - buying_settings = webnotes.bean("Buying Settings") - buying_settings.doc.supp_master_name = "Supplier Name" - buying_settings.doc.po_required = "No" - buying_settings.doc.pr_required = "No" - buying_settings.doc.maintain_same_rate = 1 - buying_settings.save() - - notification_control = webnotes.bean("Notification Control") - notification_control.doc.quotation = 1 - notification_control.doc.sales_invoice = 1 - notification_control.doc.purchase_order = 1 - notification_control.save() - - hr_settings = webnotes.bean("HR Settings") - hr_settings.doc.emp_created_by = "Naming Series" - hr_settings.save() - - # control panel - cp = webnotes.doc("Control Panel", "Control Panel") - for k in ['country', 'timezone', 'company_name']: - cp.fields[k] = args[k] - - cp.save() - - def create_feed_and_todo(self): - """update activty feed and create todo for creation of item, customer, vendor""" - import home - home.make_feed('Comment', 'ToDo', '', webnotes.session['user'], - '"' + 'Setup Complete. Please check your \ - To Do List' + '"', '#6B24B3') - - d = Document('ToDo') - d.description = 'Complete ERPNext Setup' - d.priority = 'High' - d.date = nowdate() - d.save(1) - - def create_email_digest(self): - """ - create a default weekly email digest - * Weekly Digest - * For all companies - * Recipients: System Managers - * Full content - * Enabled by default - """ - import webnotes - companies_list = webnotes.conn.sql("SELECT company_name FROM `tabCompany`", as_list=1) - - from webnotes.profile import get_system_managers - system_managers = get_system_managers() - if not system_managers: return - - from webnotes.model.doc import Document - for company in companies_list: - if company and company[0]: - edigest = webnotes.bean({ - "doctype": "Email Digest", - "name": "Default Weekly Digest - " + company[0], - "company": company[0], - "frequency": "Weekly", - "recipient_list": "\n".join(system_managers) - }) - - if webnotes.conn.sql("""select name from `tabEmail Digest` where name=%s""", edigest.doc.name): - continue - - for fieldname in edigest.meta.get_fieldnames({"fieldtype": "Check"}): - edigest.doc.fields[fieldname] = 1 - - edigest.insert() - - # Get Fiscal year Details - # ------------------------ - def get_fy_details(self, fy_start, last_year=False): - st = {'1st Jan':'01-01','1st Apr':'04-01','1st Jul':'07-01', '1st Oct': '10-01'} - if cint(getdate(nowdate()).month) < cint((st[fy_start].split('-'))[0]): - curr_year = getdate(nowdate()).year - 1 - else: - curr_year = getdate(nowdate()).year - - if last_year: - curr_year = curr_year - 1 - - stdt = cstr(curr_year)+'-'+cstr(st[fy_start]) - - if(fy_start == '1st Jan'): - fy = cstr(curr_year) - abbr = cstr(fy)[-2:] - else: - fy = cstr(curr_year) + '-' + cstr(curr_year+1) - abbr = cstr(curr_year)[-2:] + '-' + cstr(curr_year+1)[-2:] - return fy, stdt, abbr - - def create_profile(self, user_email, user_fname, user_lname, pwd=None): - pr = Document('Profile') - pr.first_name = user_fname - pr.last_name = user_lname - pr.name = pr.email = user_email - pr.enabled = 1 - pr.save(1) - if pwd: - webnotes.conn.sql("""insert into __Auth (user, `password`) - values (%s, password(%s)) - on duplicate key update `password`=password(%s)""", - (user_email, pwd, pwd)) - - add_all_roles_to(pr.name) - -def add_all_roles_to(name): - profile = webnotes.doc("Profile", name) - for role in webnotes.conn.sql("""select name from tabRole"""): - if role[0] not in ["Administrator", "Guest", "All", "Customer", "Supplier", "Partner"]: - d = profile.addchild("user_roles", "UserRole") - d.role = role[0] - d.insert() - -def create_territories(): - """create two default territories, one for home country and one named Rest of the World""" - from setup.utils import get_root_of - country = webnotes.conn.get_value("Control Panel", None, "country") - root_territory = get_root_of("Territory") - for name in (country, "Rest Of The World"): - if name and not webnotes.conn.exists("Territory", name): - webnotes.bean({ - "doctype": "Territory", - "territory_name": name.replace("'", ""), - "parent_territory": root_territory, - "is_group": "No" - }).insert() - diff --git a/setup/doctype/setup_control/setup_control.txt b/setup/doctype/setup_control/setup_control.txt deleted file mode 100644 index 7ebed3e4a13..00000000000 --- a/setup/doctype/setup_control/setup_control.txt +++ /dev/null @@ -1,24 +0,0 @@ -[ - { - "creation": "2012-03-27 14:36:25", - "docstatus": 0, - "modified": "2012-03-27 14:36:25", - "modified_by": "Administrator", - "owner": "Administrator" - }, - { - "doctype": "DocType", - "in_create": 1, - "issingle": 1, - "istable": 0, - "module": "Setup", - "name": "__common__", - "read_only": 1, - "section_style": "Simple", - "version": 73 - }, - { - "doctype": "DocType", - "name": "Setup Control" - } -] \ No newline at end of file diff --git a/setup/page/setup_wizard/setup_wizard.js b/setup/page/setup_wizard/setup_wizard.js index 7ace2ef7bf7..25c95e0b0a9 100644 --- a/setup/page/setup_wizard/setup_wizard.js +++ b/setup/page/setup_wizard/setup_wizard.js @@ -1,9 +1,59 @@ wn.pages['setup-wizard'].onload = function(wrapper) { + if(sys_defaults.company) { + wn.set_route("desktop"); + return; + } $(".navbar:first").toggle(false); + $("body").css({"padding-top":"30px"}); erpnext.wiz = new wn.wiz.Wizard({ + page_name: "setup-wizard", parent: wrapper, + on_complete: function(wiz) { + var values = wiz.get_values(); + wiz.show_working(); + console.log(values); + wn.call({ + method: "setup.page.setup_wizard.setup_wizard.setup_account", + args: values, + callback: function(r) { + if(r.exc) { + var d = msgprint(wn._("There were errors.")); + d.custom_onhide = function() { + wn.set_route(me.wiz.page_name, "0"); + } + } else { + wiz.show_complete(); + setTimeout(function() { + if(user==="Administrator") { + wn.msgprint(wn._("Login with your new User ID") + ":" + values.email); + setTimeout(function() { + wn.app.logout(); + }, 2000); + } else { + window.location = "app.html"; + } + }, 2000); + } + } + }) + }, title: wn._("ERPNext Setup Guide"), + welcome_html: '

    \ +

    '+wn._('ERPNext Setup')+'

    \ +

    ' + + wn._('Welcome to ERPNext. Over the next few minutes we will help you setup your ERPNext account. Try and fill in as much information as you have even if it takes a bit longer. It will save you a lot of time later. Good Luck!') + + '

    ', + working_html: '

    \ +

    '+wn._('Setting up...')+'

    \ +

    ' + + wn._('Sit tight while your system is being setup. This may take a few moments.') + + '

    ', + complete_html: '

    \ +

    '+wn._('Setup Complete!')+'

    \ +

    ' + + wn._('Your setup is complete. Refreshing...') + + '

    ', slides: [ // User { @@ -12,9 +62,19 @@ wn.pages['setup-wizard'].onload = function(wrapper) { fields: [ {"fieldname": "first_name", "label": wn._("First Name"), "fieldtype": "Data", reqd:1}, {"fieldname": "last_name", "label": wn._("Last Name"), "fieldtype": "Data", reqd:1}, + {"email_id": "email", "label": wn._("Email Id"), "fieldtype": "Data", reqd:1, "description":"Your Login Id"}, + {"password": "password", "label": wn._("Password"), "fieldtype": "Password", reqd:1}, {fieldtype:"Attach Image", fieldname:"attach_profile", label:"Attach Your Profile..."}, ], - help: wn._('The first user will become the System Manager (you can change that later).') + help: wn._('The first user will become the System Manager (you can change that later).'), + onload: function(slide) { + if(user!=="Administrator") { + slide.form.fields_dict.password.$wrapper.toggle(false); + slide.form.fields_dict.email_id.$wrapper.toggle(false); + delete slide.form.fields_dict.email; + delete slide.form.fields_dict.password; + } + } }, // Organization @@ -26,8 +86,11 @@ wn.pages['setup-wizard'].onload = function(wrapper) { placeholder: 'e.g. "My Company LLC"'}, {fieldname:'company_abbr', label: wn._('Company Abbreviation'), fieldtype:'Data', placeholder:'e.g. "MC"',reqd:1}, + {fieldname:'fy_start', label:'Financial Year Start Date', fieldtype:'Select', + description:'Your financial year begins on', reqd:1, + options: ['', '1st Jan', '1st Apr', '1st Jul', '1st Oct'] }, {fieldname:'company_tagline', label: wn._('What does it do?'), fieldtype:'Data', - placeholder:'e.g. "Build tools for builders"',reqd:1}, + placeholder:'e.g. "Build tools for builders"', reqd:1}, ], help: wn._('The name of your company for which you are setting up this system.'), onload: function(slide) { @@ -94,24 +157,6 @@ wn.pages['setup-wizard'].onload = function(wrapper) { {fieldtype:"Attach Image", fieldname:"attach_letterhead", label:"Attach Letterhead..."}, {fieldtype:"Attach Image", fieldname:"attach_logo", label:"Attach Logo..."}, ], - // html: '

    ' + wn._('Upload Logo') + '


    ' - // +'

    ' + wn._('Upload Letter Head') + '

    ', - onload: function(slide) { - // wn.upload.make({ - // parent: slide.$wrapper.find(".upload-area-letter-head").css({"margin-left": "10px"}), - // on_attach: function(fileobj) { - // console.log(fileobj); - // } - // }); - // - // wn.upload.make({ - // parent: slide.$wrapper.find(".upload-area-logo").css({"margin-left": "10px"}), - // on_attach: function(fileobj) { - // console.log(fileobj); - // } - // }); - } - }, // Taxes @@ -120,39 +165,46 @@ wn.pages['setup-wizard'].onload = function(wrapper) { "title": wn._("Add Taxes"), "help": wn._("List your tax heads (e.g. VAT, Excise) (upto 3) and their standard rates. This will create a standard template, you can edit and add more later."), "fields": [ - {fieldtype:"Column Break", fieldname:"cb_1", "label": "Tax Heads"}, {fieldtype:"Data", fieldname:"tax_1", label:"Tax 1", placeholder:"e.g. VAT"}, - {fieldtype:"Data", fieldname:"tax_2", label:"Tax 2", placeholder:"e.g. Customs Duty"}, - {fieldtype:"Data", fieldname:"tax_3", label:"Tax 3", placeholder:"e.g. Excise"}, - {fieldtype:"Column Break", fieldname:"cb_2", "label": "Tax Rates"}, + {fieldtype:"Column Break"}, {fieldtype:"Data", fieldname:"tax_rate_1", label:"Rate (%)", placeholder:"e.g. 5"}, + {fieldtype:"Section Break"}, + {fieldtype:"Data", fieldname:"tax_2", label:"Tax 2", placeholder:"e.g. Customs Duty"}, + {fieldtype:"Column Break"}, {fieldtype:"Data", fieldname:"tax_rate_2", label:"Rate (%)", placeholder:"e.g. 5"}, + {fieldtype:"Section Break"}, + {fieldtype:"Data", fieldname:"tax_3", label:"Tax 3", placeholder:"e.g. Excise"}, + {fieldtype:"Column Break"}, {fieldtype:"Data", fieldname:"tax_rate_3", label:"Rate (%)", placeholder:"e.g. 5"}, ], - onload: function(slide) { - } }, // Items to Sell { icon: "icon-barcode", "title": wn._("Your Products or Services"), - "help": wn._("List your products or services that you sell to your customers."), + "help": wn._("List your products or services that you sell to your customers. Make sure to check the Item Group, Unit of Measure and other properties when you start."), "fields": [ {fieldtype:"Data", fieldname:"item_1", label:"Item 1", placeholder:"A Product or Service"}, - {fieldtype:"Data", fieldname:"item_2", label:"Item 2", placeholder:"A Product or Service"}, - {fieldtype:"Data", fieldname:"item_3", label:"Item 3", placeholder:"A Product or Service"}, - {fieldtype:"Data", fieldname:"item_4", label:"Item 4", placeholder:"A Product or Service"}, - {fieldtype:"Data", fieldname:"item_5", label:"Item 5", placeholder:"A Product or Service"}, - {fieldtype:"Column Break", fieldname:"cb_2", "label": "Attachments"}, + {fieldtype:"Column Break"}, {fieldtype:"Attach", fieldname:"item_img_1", label:"Attach Image..."}, + {fieldtype:"Section Break"}, + {fieldtype:"Data", fieldname:"item_2", label:"Item 2", placeholder:"A Product or Service"}, + {fieldtype:"Column Break"}, {fieldtype:"Attach", fieldname:"item_img_2", label:"Attach Image..."}, + {fieldtype:"Section Break"}, + {fieldtype:"Data", fieldname:"item_3", label:"Item 3", placeholder:"A Product or Service"}, + {fieldtype:"Column Break"}, {fieldtype:"Attach", fieldname:"item_img_3", label:"Attach Image..."}, + {fieldtype:"Section Break"}, + {fieldtype:"Data", fieldname:"item_4", label:"Item 4", placeholder:"A Product or Service"}, + {fieldtype:"Column Break"}, {fieldtype:"Attach", fieldname:"item_img_4", label:"Attach Image..."}, + {fieldtype:"Section Break"}, + {fieldtype:"Data", fieldname:"item_5", label:"Item 5", placeholder:"A Product or Service"}, + {fieldtype:"Column Break"}, {fieldtype:"Attach", fieldname:"item_img_5", label:"Attach Image..."}, ], - onload: function(slide) { - } }, // Items to Buy @@ -167,8 +219,6 @@ wn.pages['setup-wizard'].onload = function(wrapper) { {fieldtype:"Data", fieldname:"item_buy_4", label:"Item 4", placeholder:"A Product or Service"}, {fieldtype:"Data", fieldname:"item_buy_5", label:"Item 5", placeholder:"A Product or Service"}, ], - onload: function(slide) { - } }, // Customers @@ -178,13 +228,25 @@ wn.pages['setup-wizard'].onload = function(wrapper) { "help": wn._("List a few of your customers. They could be organizations or individuals."), "fields": [ {fieldtype:"Data", fieldname:"customer_1", label:"Customer 1", placeholder:"Customer Name"}, + {fieldtype:"Column Break"}, + {fieldtype:"Data", fieldname:"customer_contact_1", label:"", placeholder:"Contact Name"}, + {fieldtype:"Section Break"}, {fieldtype:"Data", fieldname:"customer_2", label:"Customer 2", placeholder:"Customer Name"}, + {fieldtype:"Column Break"}, + {fieldtype:"Data", fieldname:"customer_contact_2", label:"", placeholder:"Contact Name"}, + {fieldtype:"Section Break"}, {fieldtype:"Data", fieldname:"customer_3", label:"Customer 3", placeholder:"Customer Name"}, + {fieldtype:"Column Break"}, + {fieldtype:"Data", fieldname:"customer_contact_3", label:"", placeholder:"Contact Name"}, + {fieldtype:"Section Break"}, {fieldtype:"Data", fieldname:"customer_4", label:"Customer 4", placeholder:"Customer Name"}, + {fieldtype:"Column Break"}, + {fieldtype:"Data", fieldname:"customer_contact_4", label:"", placeholder:"Contact Name"}, + {fieldtype:"Section Break"}, {fieldtype:"Data", fieldname:"customer_5", label:"Customer 5", placeholder:"Customer Name"}, + {fieldtype:"Column Break"}, + {fieldtype:"Data", fieldname:"customer_contact_5", label:"", placeholder:"Contact Name"}, ], - onload: function(slide) { - } }, // Suppliers @@ -194,13 +256,25 @@ wn.pages['setup-wizard'].onload = function(wrapper) { "help": wn._("List a few of your suppliers. They could be organizations or individuals."), "fields": [ {fieldtype:"Data", fieldname:"supplier_1", label:"Supplier 1", placeholder:"Supplier Name"}, + {fieldtype:"Column Break"}, + {fieldtype:"Data", fieldname:"supplier_contact_1", label:"", placeholder:"Contact Name"}, + {fieldtype:"Section Break"}, {fieldtype:"Data", fieldname:"supplier_2", label:"Supplier 2", placeholder:"Supplier Name"}, + {fieldtype:"Column Break"}, + {fieldtype:"Data", fieldname:"supplier_contact_2", label:"", placeholder:"Contact Name"}, + {fieldtype:"Section Break"}, {fieldtype:"Data", fieldname:"supplier_3", label:"Supplier 3", placeholder:"Supplier Name"}, + {fieldtype:"Column Break"}, + {fieldtype:"Data", fieldname:"supplier_contact_3", label:"", placeholder:"Contact Name"}, + {fieldtype:"Section Break"}, {fieldtype:"Data", fieldname:"supplier_4", label:"Supplier 4", placeholder:"Supplier Name"}, + {fieldtype:"Column Break"}, + {fieldtype:"Data", fieldname:"supplier_contact_4", label:"", placeholder:"Contact Name"}, + {fieldtype:"Section Break"}, {fieldtype:"Data", fieldname:"supplier_5", label:"Supplier 5", placeholder:"Supplier Name"}, + {fieldtype:"Column Break"}, + {fieldtype:"Data", fieldname:"supplier_contact_5", label:"", placeholder:"Contact Name"}, ], - onload: function(slide) { - } } ] @@ -209,7 +283,8 @@ wn.pages['setup-wizard'].onload = function(wrapper) { } wn.pages['setup-wizard'].onshow = function(wrapper) { - erpnext.wiz.show(wn.get_route()[1] || "0"); + if(wn.get_route()[1]) + erpnext.wiz.show(wn.get_route()[1]); } wn.provide("wn.wiz"); @@ -217,10 +292,45 @@ wn.provide("wn.wiz"); wn.wiz.Wizard = Class.extend({ init: function(opts) { $.extend(this, opts); + this.slides = this.slides; this.slide_dict = {}; - wn.set_route("setup-wizard", "0"); + this.show_welcome(); + }, + get_message: function(html) { + return $(repl('
    \ +
    %(html)s
    \ +
    ', {html:html})) + }, + show_welcome: function() { + if(this.$welcome) + return; + var me = this; + this.$welcome = this.get_message(this.welcome_html + + '

    ') + .appendTo(this.parent); + + this.$welcome.find(".btn").click(function() { + me.$welcome.toggle(false); + me.welcomed = true; + wn.set_route(me.page_name, "0"); + }) + + this.current_slide = {"$wrapper": this.$welcome}; + }, + show_working: function() { + this.hide_current_slide(); + wn.set_route(this.page_name); + this.current_slide = {"$wrapper": this.get_message(this.working_html).appendTo(this.parent)}; + }, + show_complete: function() { + this.hide_current_slide(); + this.current_slide = {"$wrapper": this.get_message(this.complete_html).appendTo(this.parent)}; }, show: function(id) { + if(!this.welcomed) { + wn.set_route(this.wiz.page_name); + return; + } id = cint(id); if(this.current_slide && this.current_slide.id===id) return; @@ -229,12 +339,24 @@ wn.wiz.Wizard = Class.extend({ this.slide_dict[id].make(); } - if(this.current_slide) - this.current_slide.$wrapper.toggle(false); + this.hide_current_slide(); this.current_slide = this.slide_dict[id]; this.current_slide.$wrapper.toggle(true); }, + hide_current_slide: function() { + if(this.current_slide) { + this.current_slide.$wrapper.toggle(false); + this.current_slide = null; + } + }, + get_values: function() { + var values = {}; + $.each(this.slide_dict, function(id, slide) { + $.extend(values, slide.values) + }) + return values; + } }); wn.wiz.WizardSlide = Class.extend({ @@ -249,10 +371,12 @@ wn.wiz.WizardSlide = Class.extend({
    \
    \
    \ -

    %(title)s


    \
    \
    \ -

    %(help)s

    \ +
    \ +

    %(title)s


    \ +

    %(help)s

    \ +
    \
    \
    \ \ @@ -276,17 +400,29 @@ wn.wiz.WizardSlide = Class.extend({ if(this.id > 0) { this.$prev = $("") - .click(function() { wn.set_route("setup-wizard", me.id-1 + ""); }) + .click(function() { + wn.set_route(me.wiz.page_name, me.id-1 + ""); + }) .appendTo(this.$wrapper.find(".footer")) .css({"margin-right": "5px"}); } if(this.id+1 < this.wiz.slides.length) { this.$next = $("") - .click(function() { wn.set_route("setup-wizard", me.id+1 + ""); }) + .click(function() { + me.values = me.form.get_values(); + if(me.values===null) + return; + wn.set_route(me.wiz.page_name, me.id+1 + ""); + }) .appendTo(this.$wrapper.find(".footer")); } else { this.$complete = $("") - .click(function() { me.wiz.complete(); }).appendTo(this.$wrapper.find(".footer")); + .click(function() { + me.values = me.form.get_values(); + if(me.values===null) + return; + me.wiz.on_complete(me.wiz); + }).appendTo(this.$wrapper.find(".footer")); } if(this.onload) { diff --git a/setup/page/setup_wizard/setup_wizard.py b/setup/page/setup_wizard/setup_wizard.py new file mode 100644 index 00000000000..3758b2d5bf3 --- /dev/null +++ b/setup/page/setup_wizard/setup_wizard.py @@ -0,0 +1,349 @@ +# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. +# License: GNU General Public License v3. See license.txt + +from __future__ import unicode_literals +import webnotes, json, base64 + +from webnotes.utils import cint, cstr, getdate, now, nowdate, get_defaults +from webnotes import _ +from webnotes.utils.file_manager import save_file + +@webnotes.whitelist() +def setup_account(args=None): + # if webnotes.conn.sql("select name from tabCompany"): + # webnotes.throw(_("Setup Already Complete!!")) + + if not args: + args = webnotes.local.form_dict + if isinstance(args, basestring): + args = json.loads(args) + + webnotes.conn.begin() + + update_profile_name(args) + create_fiscal_year_and_company(args) + set_defaults(args) + create_territories() + create_price_lists(args) + create_feed_and_todo() + create_email_digest() + create_taxes(args) + create_items(args) + create_customers(args) + create_suppliers(args) + webnotes.conn.set_value('Control Panel', None, 'home_page', 'desktop') + + webnotes.clear_cache() + webnotes.conn.commit() + + return "okay" + +def update_profile_name(args): + if args.get("email_id"): + args['name'] = args.get("email") + webnotes.mute_emails = True + webnotes.bean({ + "doctype":"Profile", + "email": args.get("email"), + "first_name": args.get("first_name"), + "last_name": args.get("last_name") + }).insert() + webnotes.mute_emails = False + from webnotes.auth import _update_password + _update_password(args.get("email"), args.get("password")) + + else: + args['name'] = webnotes.session.user + + # Update Profile + if not args.get('last_name') or args.get('last_name')=='None': + args['last_name'] = None + webnotes.conn.sql("""update `tabProfile` SET first_name=%(first_name)s, + last_name=%(last_name)s WHERE name=%(name)s""", args) + + if args.get("attach_profile"): + filename, filetype, content = args.get("attach_profile").split(",") + fileurl = save_file(filename, content, "Profile", args.get("name"), decode=True).file_name + webnotes.conn.set_value("Profile", args.get("name"), "user_image", fileurl) + + add_all_roles_to(args.get("name")) + +def create_fiscal_year_and_company(args): + curr_fiscal_year, fy_start_date, fy_abbr = get_fy_details(args.get('fy_start'), True) + webnotes.bean([{ + "doctype":"Fiscal Year", + 'year': curr_fiscal_year, + 'year_start_date': fy_start_date + }]).insert() + + curr_fiscal_year, fy_start_date, fy_abbr = get_fy_details(args.get('fy_start')) + webnotes.bean([{ + "doctype":"Fiscal Year", + 'year': curr_fiscal_year, + 'year_start_date': fy_start_date, + }]).insert() + + + # Company + webnotes.bean([{ + "doctype":"Company", + 'domain': args.get("industry"), + 'company_name':args.get('company_name'), + 'abbr':args.get('company_abbr'), + 'default_currency':args.get('currency'), + }]).insert() + + args["curr_fiscal_year"] = curr_fiscal_year + +def create_price_lists(args): + for pl_type in ["Selling", "Buying"]: + webnotes.bean([ + { + "doctype": "Price List", + "price_list_name": "Standard " + pl_type, + "buying_or_selling": pl_type, + "currency": args["currency"] + }, + { + "doctype": "For Territory", + "parentfield": "valid_for_territories", + "territory": "All Territories" + } + ]).insert() + +def set_defaults(args): + # enable default currency + webnotes.conn.set_value("Currency", args.get("currency"), "enabled", 1) + + global_defaults = webnotes.bean("Global Defaults", "Global Defaults") + global_defaults.doc.fields.update({ + 'current_fiscal_year': args.curr_fiscal_year, + 'default_currency': args.get('currency'), + 'default_company':args.get('company_name'), + 'date_format': webnotes.conn.get_value("Country", args.get("country"), "date_format"), + "float_precision": 4 + }) + global_defaults.save() + + accounts_settings = webnotes.bean("Accounts Settings") + accounts_settings.doc.auto_accounting_for_stock = 1 + accounts_settings.save() + + stock_settings = webnotes.bean("Stock Settings") + stock_settings.doc.item_naming_by = "Item Code" + stock_settings.doc.valuation_method = "FIFO" + stock_settings.doc.stock_uom = "Nos" + stock_settings.doc.auto_indent = 1 + stock_settings.save() + + selling_settings = webnotes.bean("Selling Settings") + selling_settings.doc.cust_master_name = "Customer Name" + selling_settings.doc.so_required = "No" + selling_settings.doc.dn_required = "No" + selling_settings.save() + + buying_settings = webnotes.bean("Buying Settings") + buying_settings.doc.supp_master_name = "Supplier Name" + buying_settings.doc.po_required = "No" + buying_settings.doc.pr_required = "No" + buying_settings.doc.maintain_same_rate = 1 + buying_settings.save() + + notification_control = webnotes.bean("Notification Control") + notification_control.doc.quotation = 1 + notification_control.doc.sales_invoice = 1 + notification_control.doc.purchase_order = 1 + notification_control.save() + + hr_settings = webnotes.bean("HR Settings") + hr_settings.doc.emp_created_by = "Naming Series" + hr_settings.save() + + # control panel + cp = webnotes.doc("Control Panel", "Control Panel") + for k in ['country', 'timezone', 'company_name']: + cp.fields[k] = args[k] + + cp.save() + +def create_feed_and_todo(): + """update activty feed and create todo for creation of item, customer, vendor""" + import home + home.make_feed('Comment', 'ToDo', '', webnotes.session['user'], + 'ERNext Setup Complete!', '#6B24B3') + +def create_email_digest(): + from webnotes.profile import get_system_managers + system_managers = get_system_managers() + if not system_managers: + return + + for company in webnotes.conn.sql_list("select name FROM `tabCompany`"): + if not webnotes.conn.exists("Email Digest", "Default Weekly Digest - " + company): + edigest = webnotes.bean({ + "doctype": "Email Digest", + "name": "Default Weekly Digest - " + company, + "company": company, + "frequency": "Weekly", + "recipient_list": "\n".join(system_managers) + }) + + for fieldname in edigest.meta.get_fieldnames({"fieldtype": "Check"}): + edigest.doc.fields[fieldname] = 1 + + edigest.insert() + +def get_fy_details(fy_start, last_year=False): + st = {'1st Jan':'01-01','1st Apr':'04-01','1st Jul':'07-01', '1st Oct': '10-01'} + if cint(getdate(nowdate()).month) < cint((st[fy_start].split('-'))[0]): + curr_year = getdate(nowdate()).year - 1 + else: + curr_year = getdate(nowdate()).year + + if last_year: + curr_year = curr_year - 1 + + stdt = cstr(curr_year)+'-'+cstr(st[fy_start]) + + if(fy_start == '1st Jan'): + fy = cstr(curr_year) + abbr = cstr(fy)[-2:] + else: + fy = cstr(curr_year) + '-' + cstr(curr_year+1) + abbr = cstr(curr_year)[-2:] + '-' + cstr(curr_year+1)[-2:] + return fy, stdt, abbr + +def create_taxes(args): + for i in xrange(1,6): + if args.get("tax_" + str(i)): + webnotes.bean({ + "doctype":"Account", + "company": args.get("company_name"), + "parent_account": "Duties and Taxes - " + args.get("company_abbr"), + "account_name": args.get("tax_" + str(i)), + "group_or_ledger": "Ledger", + "is_pl_account": "No", + "account_type": "Tax", + "tax_rate": args.get("tax_rate_" + str(i)) + }).insert() + +def create_items(args): + for i in xrange(1,6): + item = args.get("item_" + str(i)) + if item: + webnotes.bean({ + "doctype":"Item", + "item_code": item, + "item_name": item, + "description": item, + "is_sales_item": "Yes", + "is_stock_item": "Yes", + "item_group":"Products", + "stock_uom": "Unit", + "default_warehouse": "Finished Goods - " + args.get("company_abbr") + }).insert() + + if args.get("item_img_" + str(i)): + filename, filetype, content = args.get("item_img_" + str(i)).split(",") + fileurl = save_file(filename, content, "Item", item, decode=True).file_name + webnotes.conn.set_value("Item", item, "image", fileurl) + + for i in xrange(1,6): + item = args.get("item_buy_" + str(i)) + if item: + webnotes.bean({ + "doctype":"Item", + "item_code": item, + "item_name": item, + "description": item, + "is_sales_item": "No", + "is_stock_item": "Yes", + "item_group":"Raw Material", + "stock_uom": "Unit", + "default_warehouse": "Stores - " + args.get("company_abbr") + }).insert() + + if args.get("item_img_" + str(i)): + filename, filetype, content = args.get("item_img_" + str(i)).split(",") + fileurl = save_file(filename, content, "Item", item, decode=True).file_name + webnotes.conn.set_value("Item", item, "image", fileurl) + + +def create_customers(args): + for i in xrange(1,6): + customer = args.get("customer_" + str(i)) + if customer: + webnotes.bean({ + "doctype":"Customer", + "customer_name": customer, + "customer_type": "Company", + "customer_group": "Commercial", + "territory": args.get("country"), + "company": args.get("company_name") + }).insert() + + if args.get("customer_contact_" + str(i)): + contact = args.get("customer_contact_" + str(i)).split(" ") + webnotes.bean({ + "doctype":"Contact", + "customer": customer, + "first_name":contact[0], + "last_name": len(contact) > 1 and contact[1] or "" + }).insert() + +def create_suppliers(args): + for i in xrange(1,6): + supplier = args.get("supplier_" + str(i)) + if supplier: + webnotes.bean({ + "doctype":"Supplier", + "supplier_name": supplier, + "supplier_type": "Local", + "company": args.get("company_name") + }).insert() + + if args.get("supplier_contact_" + str(i)): + contact = args.get("supplier_contact_" + str(i)).split(" ") + webnotes.bean({ + "doctype":"Contact", + "supplier": supplier, + "first_name":contact[0], + "last_name": len(contact) > 1 and contact[1] or "" + }).insert() + +def create_profile(user_email, user_fname, user_lname, pwd=None): + pr = webnotes.doc('Profile') + pr.first_name = user_fname + pr.last_name = user_lname + pr.name = pr.email = user_email + pr.enabled = 1 + pr.save(1) + if pwd: + webnotes.conn.sql("""insert into __Auth (user, `password`) + values (%s, password(%s)) + on duplicate key update `password`=password(%s)""", + (user_email, pwd, pwd)) + + add_all_roles_to(pr.name) + +def add_all_roles_to(name): + profile = webnotes.doc("Profile", name) + for role in webnotes.conn.sql("""select name from tabRole"""): + if role[0] not in ["Administrator", "Guest", "All", "Customer", "Supplier", "Partner"]: + d = profile.addchild("user_roles", "UserRole") + d.role = role[0] + d.insert() + +def create_territories(): + """create two default territories, one for home country and one named Rest of the World""" + from setup.utils import get_root_of + country = webnotes.conn.get_value("Control Panel", None, "country") + root_territory = get_root_of("Territory") + for name in (country, "Rest Of The World"): + if name and not webnotes.conn.exists("Territory", name): + webnotes.bean({ + "doctype": "Territory", + "territory_name": name.replace("'", ""), + "parent_territory": root_territory, + "is_group": "No" + }).insert() \ No newline at end of file diff --git a/setup/page/setup_wizard/test_setup_data.py b/setup/page/setup_wizard/test_setup_data.py new file mode 100644 index 00000000000..dcc6b0f5cba --- /dev/null +++ b/setup/page/setup_wizard/test_setup_data.py @@ -0,0 +1,26 @@ +args = { + "attach_letterhead": "erpnext.jpg,data:image/jpeg;base64,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WVpjZGVmZ2hpanN0dXZ3eHl6goOEhYaHiImKkpOUlZaXmJmaoqOkpaanqKmqsrO0tba3uLm6wsPExcbHyMnK0tPU1dbX2Nna4uPk5ebn6Onq8vP09fb3+Pn6/9oADAMBAAIRAxEAPwD+/igAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgBGZVBZmCgAsxYgAKvLMSeAAOSTwO9AHxV4x/4KU/8E6Ph5rl74Y+IH7ff7FPgbxLps8ttqPh7xj+1R8C/DOuWFzA2ya3vdJ1rx3ZX9rPC/ySxT28ckbHa6g8UAcv/wAPYf8Agln/ANJK/wBgH/xMj9nX8f8Amo1ACf8AD2H/AIJZf9JLP2AP/EyP2de//dRu+f1oAX/h7D/wSz/6SV/sA/8AiZH7Ov8A88agA/4ew/8ABLP/AKSV/sA/+Jkfs7f/ADxqAD/h7D/wSz7/APBSv9gH/wATI/Z1/wDnjUAH/D2H/gln/wBJK/2AeOv/ABmR+zrx/wCZGoAP+HsP/BLP/pJX+wD/AOJkfs6//PGoA+hvg1+1N+zH+0al7J+z3+0b8B/jummxLcai/wAGvi98PviglhA7KqTXreCPEOuC1idnVVknKIzMoDEsMgHvHXmgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAQkKCx6AEn6Dk0Af5wP/B1n/wAFovjN4n/aI8a/8E0v2evHOs+APgv8I7LRtO/aI1jwfqt7pGs/GL4ka/olh4ivPAmra1YPbXx+HHgDSdW03StS8L2s9taeI/Gs2vt4ni1Wz0LQIbUA/iMbnOV/75VRnkf3QM/U89SeaAGjrnB6senXI/yPegAHB6HkL+HH+c/jQApJOcqeAR9ckd/8+tAC55xg9euPf/Jz/wDroARuexPH/sw4/HH5c80AGfvHDc+31/yT7/mAL3A56k5xx/F/n/8AXQB6F8Kfi18TfgZ4/wDDHxU+Dvjvxb8MviN4N1ODV/C/jbwNruoeGfE+h39vIHjnsNY0qa3uowwXy7i3leW0u4Ge2vLe4tpZYmAP9ef/AIN/v+CpWs/8FUP2FdM+JXxLTS7b9oX4P+Kp/g98dl0i1i03T/EviPTdG0zW/DvxM03R7eNLXSbP4heG9St77UdPsUt9MsvGGm+LLPRrKz0a3sLaIA/cmgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgBCMgg9Dwfcd/wA6AP8AFM/4LVzzXH/BWv8A4KLvPI8rr+2J8d4VZzkiK28a6hbW8YP92GCGKJB/CiKO1AH5gc4P178Dkr1B555+vP8AeoAQZz/30Oo3Hjue+P0oAXn+R65PQc8fr/eHSgA556dPoOvcdc46n8KADnrjv3Pqf5eg659aAA5//Wf9rv6jB/DJHegBOfm6Z4789O/9emRmgBecj6nvx1bt6/5NABzx069zk/e556env2oA/wBDj/gx5mmf4Yf8FErdpGMEPjv9mqeKInKRzT+GPi/FPIo7PLHbQI57rEg/hoA/u7oAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKAP8AFF/4LS/8paf+CjPr/wANkfH3/wBTvVPf/wDX60AfmMc4Of8A638PU8H1/wA4oAQZyPXLc8dcc9+oP4GgAGc47kLnt0A98nvnj/64ApyScjsR147d+OvvjjmgAyc49we3r9c/Q9c8HrQAN7+/6sMDr7df60AHPzevGenp356EfzPXFABzkdcZPp1+b3z/AJ9aADnAHvknj+96e/8AkmgD/Q0/4Md/+Sb/APBRf/sdf2ZP/Ub+M1AH939ABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQB/ijf8ABaX/AJS0/wDBRn/s8j4+8/8Ac+ap3/zzQB+Y3+Prx1Ht/TqT60AIM+p/i53c+nPH5dcGgBec9+MdT+PoefXnoe+RQAvPX29ePr06/gaADBz1PXPX8x06fj+XWgBDn3/P1P8AnHXjIoAOeRz25z/9bvxnPqT9QA7g5PUjrx3P+fT8KADkfn1J56/5789OtAH+hn/wY7/8k3/4KL/9jr+zJ/6jfxmoA/u/oAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKAP8UX/AILS/wDKWn/gozxn/jMj4+9s/wDM+ap+fNAH5jEdeP8Ax0H+76/j+vpQAgHPT1/g/L3/AK9jQAd+hxx/APxoAO7cHv8AwD1/X/JoACOenf8AuZH59f8APFACkdePX+EH+L/D9OaAE7Hj0/gH4/8A1/060ALjnoOp/g7c9+n4/ie9ABj2/wDHPf8AT8e3PWgD/Q0/4Md/+Sb/APBRf/sdf2ZP/Ub+M3+fegD+7+gAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoA/xRf+C0v/KWn/goz/2eR8fffr481X/P55oA/Mc85P8AMH1HXuenP/6qAGjqOB1bnB75xn2Pbnp34NAC4Oc46Y7ZPAHTk/j+mTQAYPXA5z29wfm75/Dr3oAMHrhfXpz/ACz75657UABHt+nqwPPf/HnPNAAAeRgdeuODj/PPpk0AHcH/AGj2OepOeme/596ADHTgdR7H72eOvGPf1zQB/oaf8GO//JN/+Ci//Y6/syf+o38ZqAP7v6ACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKAMzWda0jw7pOp69r+qadomiaLp97q+saxq99a6ZpWk6VptvJeajqep6jfTQWWn6fY2sUtzeX15PDa2sEbzTyxxqWAB+H/AMUv+DlH/giz8JfE194T139trwp4k1bTbmW0vp/hl4A+LfxT8PRzRMysLXxf4D8C654U1WLKnFxo+s6hbE8CY9wDzP8A4io/+CIf/R2mu/8AiPH7RX/zsqAD/iKj/wCCIf8A0dprv/iPH7RX/wA7KgA/4io/+CIf/R2mu/8AiPH7RX/zsqAD/iKj/wCCIf8A0dprv/iPH7RX/wA7KgA/4io/+CIf/R2mu/8AiPH7RX/zsqAP8xH/AIKa/Gj4d/tF/wDBQn9s747/AAi1yTxN8MPi7+0n8XPiF4B8QTaVquhzaz4U8U+LL/VNE1J9H12007WdNa7sp45WstTsbS+t9xjubeGUFFAPho55+uc8e3v25/TnPUATJz27+mef+Bfn/XrQADIPYZx6c8fX/H+VAC5OfpnnjPb/AGvz6dqADJz/APqzj/vr8KAA5/rzj1Hv6fTmgBMnnp79P1+b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ABQAUAFABQAUAFABQAUAFABQAUAFABQAUAf4ov8AwWk/5Sz/APBRrP8A0eT8f/8A1PdU/pn/ABoA/MY9fTnv/wAB75Pt/XvkATg9x/F+H6jr3yfpgcgAUfUdvqcYOP5YwfqTzQAHHJyffkZHPTOfU/8A1+xADj15znqM56Z69fXtj+HNAB+P5/73+POcYzjoOKADjnnuOhHp9evHHOOmckGgA79ecn69W/n3yMcn2AAAY459OMjHX6k/r168cUAf6Gn/AAY7/wDJN/8Agov/ANjr+zJ/6jfxmoA/u/oAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKAP8AFF/4LSf8pZ/+CjX/AGeT8f8A/wBT3VKAPzFJ5J9+/wBU70AGQe3Zsc+uc8Y/LP60AGf129+eAPbn8+DycA0AGeSe+PUdMj2wP1Pr2oAM8/8AAj375+np+GOPvUABP9T1/wBv/PJ/xoAM8Hp1Hf29+e3f8ehoAUfeHrk/zb/PX0oAQHgDscdSP73p1NAH+hr/AMGO/wDyTf8A4KL/APY6/syf+o38Zs0Af3f0AFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFAH+KL/wWj/5S0f8FGucf8Zk/H/r/wBj7qn/AOv9fqAfmOfbHXp+K+3uT+INADefUfxenb8PXk9c9aAF5yeR2z05yB7c5/Cg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BQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFAH/2Q==", + "attach_logo": "logo-2013-color-small.png,data:image/png;base64,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", + "attach_profile": "rushabh.jpeg,data:image/jpeg;base64,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", + "company_abbr": "WN", + "company_name": "Web Notes", + "company_tagline": "Open Source ERP", + "country": "India", + "currency": "INR", + "customer_1": "RIGPL", + "customer_2": "Mahesh Engg", + "customer_contact_1": "Aditya Duggal", + "customer_contact_2": "Mahesh Malani", + "first_name": "Rushabh", + "fy_start": "1st Apr", + "item_1": "Enterprise", + "item_2": "Small Business", + "item_3": "Solo", + "item_buy_1": "Adwords", + "item_buy_2": "Server Hosting", + "item_img_1": "logo-2013-color-small.png,data:image/png;base64,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", + "last_name": "Mehta", + "tax_1": "Service Tax", + "tax_rate_1": "12.5", + "timezone": "Asia/Calcutta" +} \ No newline at end of file diff --git a/setup/page/setup_wizard/test_setup_wizard.py b/setup/page/setup_wizard/test_setup_wizard.py new file mode 100644 index 00000000000..7f09a9bfeab --- /dev/null +++ b/setup/page/setup_wizard/test_setup_wizard.py @@ -0,0 +1,14 @@ +# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. +# License: GNU General Public License v3. See license.txt + +from __future__ import unicode_literals +import webnotes + +from setup.page.setup_wizard.test_setup_data import args +from setup.page.setup_wizard.setup_wizard import setup_account + +if __name__=="__main__": + webnotes.connect() + webnotes.local.form_dict = webnotes._dict(args) + setup_account() + \ No newline at end of file diff --git a/startup/install.py b/startup/install.py index d79559426be..59b74965b9e 100644 --- a/startup/install.py +++ b/startup/install.py @@ -13,13 +13,13 @@ def post_import(): import_country_and_currency() # home page - webnotes.conn.set_value('Control Panel', None, 'home_page', 'desktop') + webnotes.conn.set_value('Control Panel', None, 'home_page', 'setup-wizard') # features feature_setup() # all roles to Administrator - from setup.doctype.setup_control.setup_control import add_all_roles_to + from setup.page.setup_wizard.setup_wizard import add_all_roles_to add_all_roles_to("Administrator") webnotes.conn.commit() diff --git a/utilities/demo/make_demo.py b/utilities/demo/make_demo.py index 692ae311105..62371a36c81 100644 --- a/utilities/demo/make_demo.py +++ b/utilities/demo/make_demo.py @@ -376,7 +376,8 @@ def install(): def complete_setup(): print "Complete Setup..." - webnotes.get_obj("Setup Control").setup_account({ + from setup.page.setup_wizard.setup_wizard import setup_account + setup_account({ "first_name": "Test", "last_name": "User", "fy_start": "1st Jan", diff --git a/utilities/doctype/contact/contact.txt b/utilities/doctype/contact/contact.txt index db23410820f..199aaea82ef 100644 --- a/utilities/doctype/contact/contact.txt +++ b/utilities/doctype/contact/contact.txt @@ -2,7 +2,7 @@ { "creation": "2013-01-10 16:34:32", "docstatus": 0, - "modified": "2013-10-03 16:44:08", + "modified": "2013-10-08 16:48:50", "modified_by": "Administrator", "owner": "Administrator" }, @@ -85,7 +85,7 @@ "label": "Email Id", "oldfieldname": "email_id", "oldfieldtype": "Data", - "reqd": 1, + "reqd": 0, "search_index": 1 }, { @@ -95,7 +95,7 @@ "label": "Phone", "oldfieldname": "contact_no", "oldfieldtype": "Data", - "reqd": 1 + "reqd": 0 }, { "doctype": "DocField", From 5d455577297c50934ca40ad7ed0367127727a3cc Mon Sep 17 00:00:00 2001 From: Rushabh Mehta Date: Tue, 8 Oct 2013 18:23:05 +0530 Subject: [PATCH 134/200] [wsgi] [minor] fixed flags --- .../production_planning_tool/production_planning_tool.py | 4 ++-- setup/page/setup_wizard/setup_wizard.js | 3 +-- setup/page/setup_wizard/setup_wizard.py | 9 ++++++--- startup/__init__.py | 2 -- utilities/demo/make_demo.py | 6 +++--- utilities/demo/make_erpnext_demo.py | 2 +- 6 files changed, 13 insertions(+), 13 deletions(-) diff --git a/manufacturing/doctype/production_planning_tool/production_planning_tool.py b/manufacturing/doctype/production_planning_tool/production_planning_tool.py index 5480f177d92..6f15d4c9f10 100644 --- a/manufacturing/doctype/production_planning_tool/production_planning_tool.py +++ b/manufacturing/doctype/production_planning_tool/production_planning_tool.py @@ -215,14 +215,14 @@ class DocType: pro = webnotes.new_bean("Production Order") pro.doc.fields.update(items[key]) - webnotes.mute_messages = True + webnotes.flags.mute_messages = True try: pro.insert() pro_list.append(pro.doc.name) except OverProductionError, e: pass - webnotes.mute_messages = False + webnotes.flags.mute_messages = False return pro_list diff --git a/setup/page/setup_wizard/setup_wizard.js b/setup/page/setup_wizard/setup_wizard.js index 25c95e0b0a9..905b6a97693 100644 --- a/setup/page/setup_wizard/setup_wizard.js +++ b/setup/page/setup_wizard/setup_wizard.js @@ -12,7 +12,6 @@ wn.pages['setup-wizard'].onload = function(wrapper) { on_complete: function(wiz) { var values = wiz.get_values(); wiz.show_working(); - console.log(values); wn.call({ method: "setup.page.setup_wizard.setup_wizard.setup_account", args: values, @@ -26,7 +25,7 @@ wn.pages['setup-wizard'].onload = function(wrapper) { wiz.show_complete(); setTimeout(function() { if(user==="Administrator") { - wn.msgprint(wn._("Login with your new User ID") + ":" + values.email); + msgprint(wn._("Login with your new User ID") + ":" + values.email); setTimeout(function() { wn.app.logout(); }, 2000); diff --git a/setup/page/setup_wizard/setup_wizard.py b/setup/page/setup_wizard/setup_wizard.py index 3758b2d5bf3..714df2ec0fa 100644 --- a/setup/page/setup_wizard/setup_wizard.py +++ b/setup/page/setup_wizard/setup_wizard.py @@ -35,20 +35,23 @@ def setup_account(args=None): webnotes.clear_cache() webnotes.conn.commit() + + # suppress msgprints + webnotes.local.message_log = [] return "okay" def update_profile_name(args): - if args.get("email_id"): + if args.get("email"): args['name'] = args.get("email") - webnotes.mute_emails = True + webnotes.flags.mute_emails = True webnotes.bean({ "doctype":"Profile", "email": args.get("email"), "first_name": args.get("first_name"), "last_name": args.get("last_name") }).insert() - webnotes.mute_emails = False + webnotes.flags.mute_emails = False from webnotes.auth import _update_password _update_password(args.get("email"), args.get("password")) diff --git a/startup/__init__.py b/startup/__init__.py index 227846c46dc..802daac9b3b 100644 --- a/startup/__init__.py +++ b/startup/__init__.py @@ -27,8 +27,6 @@ profile_defaults = { "Territory": "territory" } -application_home_page = "desktop" - # add startup propertes mail_footer = """
    Sent via ERPNext
    """ diff --git a/utilities/demo/make_demo.py b/utilities/demo/make_demo.py index 62371a36c81..d335528dfc7 100644 --- a/utilities/demo/make_demo.py +++ b/utilities/demo/make_demo.py @@ -30,9 +30,9 @@ prob = { } def make(reset=False, simulate=True): - #webnotes.print_messages = True - webnotes.mute_emails = True - webnotes.rollback_on_exception = True + #webnotes.flags.print_messages = True + webnotes.flags.mute_emails = True + webnotes.flags.rollback_on_exception = True if not webnotes.conf.demo_db_name: raise Exception("conf.py does not have demo_db_name") diff --git a/utilities/demo/make_erpnext_demo.py b/utilities/demo/make_erpnext_demo.py index a57441b556e..d67fb5ece01 100644 --- a/utilities/demo/make_erpnext_demo.py +++ b/utilities/demo/make_erpnext_demo.py @@ -6,7 +6,7 @@ import webnotes, os import utilities.demo.make_demo def make_demo_app(site=None): - webnotes.mute_emails = 1 + webnotes.flags.mute_emails = 1 webnotes.init(site=site) utilities.demo.make_demo.make(reset=True, simulate=False) From 2dcfbd16421ecccf5b327c7c6b4e823ab7ed73ae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A1rbara=20Perretti?= Date: Tue, 8 Oct 2013 14:35:14 -0300 Subject: [PATCH 135/200] Fix translate purchase_trends_filters.js --- public/js/purchase_trends_filters.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/public/js/purchase_trends_filters.js b/public/js/purchase_trends_filters.js index 5a13066a249..62d7fd26504 100644 --- a/public/js/purchase_trends_filters.js +++ b/public/js/purchase_trends_filters.js @@ -5,35 +5,35 @@ var get_filters = function(){ return [ { "fieldname":"period", - "label": "Period", + "label": wn._("Period"), "fieldtype": "Select", "options": ["Monthly", "Quarterly", "Half-Yearly", "Yearly"].join("\n"), "default": "Monthly" }, { "fieldname":"based_on", - "label": "Based On", + "label": wn._("Based On"), "fieldtype": "Select", "options": ["Item", "Item Group", "Supplier", "Supplier Type", "Project"].join("\n"), "default": "Item" }, { "fieldname":"group_by", - "label": "Group By", + "label": wn._("Group By"), "fieldtype": "Select", "options": ["Item", "Supplier"].join("\n"), "default": "" }, { "fieldname":"fiscal_year", - "label": "Fiscal Year", + "label": wn._("Fiscal Year"), "fieldtype": "Link", "options":'Fiscal Year', "default": sys_defaults.fiscal_year }, { "fieldname":"company", - "label": "Company", + "label": wn._("Company"), "fieldtype": "Link", "options": "Company", "default": wn.defaults.get_default("company") From 2368004cb0565c832ebe6d87f8feb2ff3b356071 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A1rbara=20Perretti?= Date: Tue, 8 Oct 2013 14:41:46 -0300 Subject: [PATCH 136/200] Fix translate sales_trends_filters.js --- public/js/sales_trends_filters.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/public/js/sales_trends_filters.js b/public/js/sales_trends_filters.js index 63f6e63e5a0..29bb779b4a5 100644 --- a/public/js/sales_trends_filters.js +++ b/public/js/sales_trends_filters.js @@ -5,35 +5,35 @@ var get_filters = function(){ return[ { "fieldname":"period", - "label": "Period", + "label": wn._("Period"), "fieldtype": "Select", "options": ["Monthly", "Quarterly", "Half-Yearly", "Yearly"].join("\n"), "default": "Monthly" }, { "fieldname":"based_on", - "label": "Based On", + "label": wn._("Based On"), "fieldtype": "Select", "options": ["Item", "Item Group", "Customer", "Customer Group", "Territory", "Project"].join("\n"), "default": "Item" }, { "fieldname":"group_by", - "label": "Group By", + "label": wn._("Group By"), "fieldtype": "Select", "options": ["Item", "Customer"].join("\n"), "default": "" }, { "fieldname":"fiscal_year", - "label": "Fiscal Year", + "label": wn._("Fiscal Year"), "fieldtype": "Link", "options":'Fiscal Year', "default": sys_defaults.fiscal_year }, { "fieldname":"company", - "label": "Company", + "label": wn._("Company"), "fieldtype": "Link", "options": "Company", "default": wn.defaults.get_default("company") From e5b83d7995ebe9ad88573f559b4b57da2f4ceb82 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A1rbara=20Perretti?= Date: Tue, 8 Oct 2013 14:48:34 -0300 Subject: [PATCH 137/200] Fix translate startup.js --- public/js/startup.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/public/js/startup.js b/public/js/startup.js index eee8a056208..4b58c4cadbd 100644 --- a/public/js/startup.js +++ b/public/js/startup.js @@ -6,7 +6,7 @@ var current_module; wn.provide('erpnext.startup'); erpnext.startup.start = function() { - console.log('Starting up...'); + console.log(wn._('Starting up...')); $('#startup_div').html('Starting up...').toggle(true); if(user != 'Guest'){ @@ -35,16 +35,16 @@ erpnext.startup.show_expiry_banner = function() { var today = dateutil.str_to_obj(wn.boot.server_date); var expires_on = dateutil.str_to_obj(wn.boot.expires_on); var diff = dateutil.get_diff(expires_on, today); - var payment_link = "\ - Click here to buy subscription."; + var payment_link = ""+ + wn._("Click here to buy subscription.")+""; var msg = ""; if (0 <= diff && diff <= 10) { var expiry_string = diff==0 ? "today" : repl("in %(diff)s day(s)", { diff: diff }); - msg = repl('Your ERPNext subscription will expire %(expiry_string)s. %(payment_link)s', + msg = repl(wn._('Your ERPNext subscription will expire %(expiry_string)s. %(payment_link)s')), { expiry_string: expiry_string, payment_link: payment_link }); } else if (diff < 0) { - msg = repl('This ERPNext subscription has expired. %(payment_link)s', {payment_link: payment_link}); + msg = repl(wn._('This ERPNext subscription has expired. %(payment_link)s'), {payment_link: payment_link}); } if(msg) wn.ui.toolbar.show_banner(msg); From fa567a11904c910e1a1a04ca0e7fea5558838b1a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A1rbara=20Perretti?= Date: Tue, 8 Oct 2013 14:56:03 -0300 Subject: [PATCH 138/200] Fix translate stock_analytics.js --- public/js/stock_analytics.js | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/public/js/stock_analytics.js b/public/js/stock_analytics.js index 5b581130463..8cb61616360 100644 --- a/public/js/stock_analytics.js +++ b/public/js/stock_analytics.js @@ -6,7 +6,7 @@ wn.require("app/js/stock_grid_report.js"); erpnext.StockAnalytics = erpnext.StockGridReport.extend({ init: function(wrapper, opts) { var args = { - title: "Stock Analytics", + title: wn._("Stock Analytics"), page: wrapper, parent: $(wrapper).find('.layout-main'), appframe: wrapper.appframe, @@ -36,13 +36,13 @@ erpnext.StockAnalytics = erpnext.StockGridReport.extend({ }, setup_columns: function() { var std_columns = [ - {id: "check", name: "Plot", field: "check", width: 30, + {id: "check", name: wn._("Plot"), field: "check", width: 30, formatter: this.check_formatter}, - {id: "name", name: "Item", field: "name", width: 300, + {id: "name", name: wn._("Item"), field: "name", width: 300, formatter: this.tree_formatter}, - {id: "brand", name: "Brand", field: "brand", width: 100}, - {id: "stock_uom", name: "UOM", field: "stock_uom", width: 100}, - {id: "opening", name: "Opening", field: "opening", hidden: true, + {id: "brand", name: wn._("Brand"), field: "brand", width: 100}, + {id: "stock_uom", name: wn._("UOM"), field: "stock_uom", width: 100}, + {id: "opening", name: wn._("Opening"), field: "opening", hidden: true, formatter: this.currency_formatter} ]; @@ -50,23 +50,23 @@ erpnext.StockAnalytics = erpnext.StockGridReport.extend({ this.columns = std_columns.concat(this.columns); }, filters: [ - {fieldtype:"Select", label: "Value or Qty", options:["Value", "Quantity"], + {fieldtype:"Select", label: wn._("Value or Qty"), options:["Value", "Quantity"], filter: function(val, item, opts, me) { return me.apply_zero_filter(val, item, opts, me); }}, - {fieldtype:"Select", label: "Brand", link:"Brand", + {fieldtype:"Select", label: wn._("Brand"), link:"Brand", default_value: "Select Brand...", filter: function(val, item, opts) { return val == opts.default_value || item.brand == val || item._show; }, link_formatter: {filter_input: "brand"}}, - {fieldtype:"Select", label: "Warehouse", link:"Warehouse", + {fieldtype:"Select", label: wn._("Warehouse"), link:"Warehouse", default_value: "Select Warehouse..."}, - {fieldtype:"Date", label: "From Date"}, - {fieldtype:"Label", label: "To"}, - {fieldtype:"Date", label: "To Date"}, - {fieldtype:"Select", label: "Range", + {fieldtype:"Date", label: wn._("From Date")}, + {fieldtype:"Label", label: wn._("To")}, + {fieldtype:"Date", label: wn._("To Date")}, + {fieldtype:"Select", label: wn._("Range"), options:["Daily", "Weekly", "Monthly", "Quarterly", "Yearly"]}, - {fieldtype:"Button", label: "Refresh", icon:"icon-refresh icon-white", cssClass:"btn-info"}, - {fieldtype:"Button", label: "Reset Filters"} + {fieldtype:"Button", label: wn._("Refresh"), icon:"icon-refresh icon-white", cssClass:"btn-info"}, + {fieldtype:"Button", label: wn._("Reset Filters")} ], setup_filters: function() { var me = this; From 534af0bccaab074eb46317acd7344b02020a44e9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A1rbara=20Perretti?= Date: Tue, 8 Oct 2013 15:00:07 -0300 Subject: [PATCH 139/200] Fix translate transaction.js --- public/js/transaction.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/public/js/transaction.js b/public/js/transaction.js index 387140472c7..3080ba17210 100644 --- a/public/js/transaction.js +++ b/public/js/transaction.js @@ -234,7 +234,7 @@ erpnext.TransactionController = erpnext.stock.StockController.extend({ validate_on_previous_row: function(tax) { // validate if a valid row id is mentioned in case of // On Previous Row Amount and On Previous Row Total - if((["On Previous Row Amount", "On Previous Row Total"].indexOf(tax.charge_type) != -1) && + if(([wn._("On Previous Row Amount"), wn._("On Previous Row Total")].indexOf(tax.charge_type) != -1) && (!tax.row_id || cint(tax.row_id) >= tax.idx)) { var msg = repl(wn._("Row") + " # %(idx)s [%(doctype)s]: " + wn._("Please specify a valid") + " %(row_id_label)s", { From 961d2e210434f6b8d4908eb6a6355b6920e2a629 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A1rbara=20Perretti?= Date: Tue, 8 Oct 2013 15:01:37 -0300 Subject: [PATCH 140/200] Fix translate utils.js --- public/js/utils.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/public/js/utils.js b/public/js/utils.js index 61e613bdecb..a8df11e9337 100644 --- a/public/js/utils.js +++ b/public/js/utils.js @@ -41,19 +41,19 @@ $.extend(erpnext, { if(!grid_row.fields_dict.serial_no || grid_row.fields_dict.serial_no.get_status()!=="Write") return; - var $btn = $('') + var $btn = $('') .appendTo($("
    ") .css({"margin-bottom": "10px", "margin-top": "-10px"}) .appendTo(grid_row.fields_dict.serial_no.$wrapper)); $btn.on("click", function() { var d = new wn.ui.Dialog({ - title: "Add Serial No", + title: wn._("Add Serial No"), fields: [ { "fieldtype": "Link", "options": "Serial No", - "label": "Serial No", + "label": wn._("Serial No"), "get_query": { item_code: grid_row.doc.item_code, warehouse: grid_row.doc.warehouse @@ -61,7 +61,7 @@ $.extend(erpnext, { }, { "fieldtype": "Button", - "label": "Add" + "label": wn._("Add") } ] }); From ac6fc6fab648003d6c050e9cc83f39a6c00059c2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A1rbara=20Perretti?= Date: Tue, 8 Oct 2013 15:13:25 -0300 Subject: [PATCH 141/200] Fix translate project.js --- projects/doctype/project/project.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/projects/doctype/project/project.js b/projects/doctype/project/project.js index 74cfa45198b..3dfe8973839 100644 --- a/projects/doctype/project/project.js +++ b/projects/doctype/project/project.js @@ -4,11 +4,11 @@ // show tasks cur_frm.cscript.refresh = function(doc) { if(!doc.__islocal) { - cur_frm.add_custom_button("Gantt Chart", function() { + cur_frm.add_custom_button(wn._("Gantt Chart"), function() { wn.route_options = {"project": doc.name} wn.set_route("Gantt", "Task"); }, "icon-tasks"); - cur_frm.add_custom_button("Tasks", function() { + cur_frm.add_custom_button(wn._("Tasks"), function() { wn.route_options = {"project": doc.name} wn.set_route("List", "Task"); }, "icon-list"); From f4cde68097867ac3390a762028707f9b3ba33bc8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A1rbara=20Perretti?= Date: Tue, 8 Oct 2013 15:17:44 -0300 Subject: [PATCH 142/200] Fix translate time_log_calendar.js --- projects/doctype/task/task_calendar.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/projects/doctype/task/task_calendar.js b/projects/doctype/task/task_calendar.js index 77728553e06..29d1c9940bb 100644 --- a/projects/doctype/task/task_calendar.js +++ b/projects/doctype/task/task_calendar.js @@ -6,7 +6,7 @@ wn.views.calendar["Task"] = { "start": "exp_start_date", "end": "exp_end_date", "id": "name", - "title": "subject", + "title": wn._("subject"), "allDay": "allDay" }, gantt: true, @@ -15,7 +15,7 @@ wn.views.calendar["Task"] = { "fieldtype": "Link", "fieldname": "project", "options": "Project", - "label": "Project" + "label": wn._("Project") } ], get_events_method: "projects.doctype.task.task.get_events" From e52998fd12a43efe8421ad140f83c959b6fcd550 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A1rbara=20Perretti?= Date: Tue, 8 Oct 2013 15:19:18 -0300 Subject: [PATCH 143/200] Fix translate time_log_calendar.js --- projects/doctype/time_log/time_log_calendar.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/projects/doctype/time_log/time_log_calendar.js b/projects/doctype/time_log/time_log_calendar.js index a4f22db3294..12cfcba5620 100644 --- a/projects/doctype/time_log/time_log_calendar.js +++ b/projects/doctype/time_log/time_log_calendar.js @@ -6,7 +6,7 @@ wn.views.calendar["Time Log"] = { "start": "from_time", "end": "to_time", "id": "name", - "title": "title", + "title": w._("title"), "allDay": "allDay" }, get_events_method: "projects.doctype.time_log.time_log.get_events" From e9c36599f516df73fb93793a358a00c2852be2b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A1rbara=20Perretti?= Date: Tue, 8 Oct 2013 15:23:51 -0300 Subject: [PATCH 144/200] Fix translate time_log_batch.js --- projects/doctype/time_log_batch/time_log_batch.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/projects/doctype/time_log_batch/time_log_batch.js b/projects/doctype/time_log_batch/time_log_batch.js index 96f7c2229df..c338c401a18 100644 --- a/projects/doctype/time_log_batch/time_log_batch.js +++ b/projects/doctype/time_log_batch/time_log_batch.js @@ -25,7 +25,7 @@ $.extend(cur_frm.cscript, { }[doc.status]); if(doc.status=="Submitted") { - cur_frm.add_custom_button("Make Sales Invoice", function() { cur_frm.cscript.make_invoice() }, + cur_frm.add_custom_button(wn._("Make Sales Invoice"), function() { cur_frm.cscript.make_invoice() }, "icon-file-alt"); } }, From 91d9ddd4f04a575f1b8732251bd444a9c7ef6b7d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A1rbara=20Perretti?= Date: Tue, 8 Oct 2013 15:45:58 -0300 Subject: [PATCH 145/200] Fix translate demo-login.js --- utilities/demo/demo-login.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/utilities/demo/demo-login.js b/utilities/demo/demo-login.js index 509057b9ef9..03fe6b96b91 100644 --- a/utilities/demo/demo-login.js +++ b/utilities/demo/demo-login.js @@ -14,9 +14,9 @@ $(document).ready(function() { callback: function(r) { $(me).prop("disabled", false); if(r.exc) { - alert("Error, please contact support@erpnext.com"); + alert(wn._("Error, please contact support@erpnext.com")); } else { - console.log("Logged In"); + console.log(wn._("Logged In")); window.location.href = "app.html"; } } From ddca90ef7b063e0846d59e71167a4b44e33e943a Mon Sep 17 00:00:00 2001 From: Rushabh Mehta Date: Wed, 9 Oct 2013 16:08:54 +0530 Subject: [PATCH 146/200] [communication] [setup wizard] [minor] [fixes] --- .../job_applicant/get_job_applications.py | 2 +- selling/doctype/customer/customer.js | 1 - selling/doctype/lead/get_leads.py | 2 +- setup/page/setup_wizard/setup_wizard.css | 8 ++ setup/page/setup_wizard/setup_wizard.js | 72 +++++++++++++++++- setup/page/setup_wizard/setup_wizard.py | 47 ++++++------ setup/page/setup_wizard/test_setup_data.py | 75 +++++++++++++------ startup/install.py | 1 + .../support_ticket/get_support_mails.py | 2 +- 9 files changed, 156 insertions(+), 54 deletions(-) create mode 100644 setup/page/setup_wizard/setup_wizard.css diff --git a/hr/doctype/job_applicant/get_job_applications.py b/hr/doctype/job_applicant/get_job_applications.py index 2e013289159..a9297810193 100644 --- a/hr/doctype/job_applicant/get_job_applications.py +++ b/hr/doctype/job_applicant/get_job_applications.py @@ -37,7 +37,7 @@ class JobsMailbox(POP3Mailbox): mail.save_attachments_in_doc(applicant.doc) make(content=mail.content, sender=mail.from_email, - doctype="Job Applicant", name=applicant.doc.name) + doctype="Job Applicant", name=applicant.doc.name, sent_or_received="Received") def get_job_applications(): if cint(webnotes.conn.get_value('Jobs Email Settings', None, 'extract_emails')): diff --git a/selling/doctype/customer/customer.js b/selling/doctype/customer/customer.js index d2c632530b3..a38ab9cbf00 100644 --- a/selling/doctype/customer/customer.js +++ b/selling/doctype/customer/customer.js @@ -34,7 +34,6 @@ cur_frm.cscript.refresh = function(doc,dt,dn) { cur_frm.cscript.make_contact(doc,dt,dn); cur_frm.communication_view = new wn.views.CommunicationList({ - list: wn.model.get("Communication", {"customer": doc.name}), parent: cur_frm.fields_dict.communication_html.wrapper, doc: doc, }); diff --git a/selling/doctype/lead/get_leads.py b/selling/doctype/lead/get_leads.py index 3305a3b9f6e..eaf837bb5be 100644 --- a/selling/doctype/lead/get_leads.py +++ b/selling/doctype/lead/get_leads.py @@ -29,7 +29,7 @@ def add_sales_communication(subject, content, sender, real_name, mail=None, parent_name = contact_name or lead_name message = make(content=content, sender=sender, subject=subject, - doctype = parent_doctype, name = parent_name, date=date) + doctype = parent_doctype, name = parent_name, date=date, sent_or_received="Received") if mail: # save attachments to parent if from mail diff --git a/setup/page/setup_wizard/setup_wizard.css b/setup/page/setup_wizard/setup_wizard.css new file mode 100644 index 00000000000..ad49ef0c049 --- /dev/null +++ b/setup/page/setup_wizard/setup_wizard.css @@ -0,0 +1,8 @@ +#page-setup-wizard .panel { + -webkit-box-shadow: 0px 1px 8px rgba(0,0,0,0.6); + box-shadow: 0px 1px 8px rgba(0,0,0,0.6); +} + +#page-setup-wizard .col-md-6 .control-input .btn { + width: 100%; +} diff --git a/setup/page/setup_wizard/setup_wizard.js b/setup/page/setup_wizard/setup_wizard.js index 905b6a97693..648958e6267 100644 --- a/setup/page/setup_wizard/setup_wizard.js +++ b/setup/page/setup_wizard/setup_wizard.js @@ -19,7 +19,7 @@ wn.pages['setup-wizard'].onload = function(wrapper) { if(r.exc) { var d = msgprint(wn._("There were errors.")); d.custom_onhide = function() { - wn.set_route(me.wiz.page_name, "0"); + wn.set_route(erpnext.wiz.page_name, "0"); } } else { wiz.show_complete(); @@ -61,8 +61,8 @@ wn.pages['setup-wizard'].onload = function(wrapper) { fields: [ {"fieldname": "first_name", "label": wn._("First Name"), "fieldtype": "Data", reqd:1}, {"fieldname": "last_name", "label": wn._("Last Name"), "fieldtype": "Data", reqd:1}, - {"email_id": "email", "label": wn._("Email Id"), "fieldtype": "Data", reqd:1, "description":"Your Login Id"}, - {"password": "password", "label": wn._("Password"), "fieldtype": "Password", reqd:1}, + {"fieldname": "email", "label": wn._("Email Id"), "fieldtype": "Data", reqd:1, "description":"Your Login Id"}, + {"fieldname": "password", "label": wn._("Password"), "fieldtype": "Password", reqd:1}, {fieldtype:"Attach Image", fieldname:"attach_profile", label:"Attach Your Profile..."}, ], help: wn._('The first user will become the System Manager (you can change that later).'), @@ -188,21 +188,51 @@ wn.pages['setup-wizard'].onload = function(wrapper) { {fieldtype:"Column Break"}, {fieldtype:"Attach", fieldname:"item_img_1", label:"Attach Image..."}, {fieldtype:"Section Break"}, + {fieldtype:"Column Break"}, + {fieldtype:"Column Break"}, + {fieldtype:"Select", fieldname:"item_group_1", options:["Products", "Services", "Raw Material", "Sub Assemblies"]}, + {fieldtype:"Column Break"}, + {fieldtype:"Select", fieldname:"item_uom_1", options:["Unit", "Nos", "Box", "Pair", "Kg", "Set", "Hour", "Minute"]}, + {fieldtype:"Section Break"}, {fieldtype:"Data", fieldname:"item_2", label:"Item 2", placeholder:"A Product or Service"}, {fieldtype:"Column Break"}, {fieldtype:"Attach", fieldname:"item_img_2", label:"Attach Image..."}, {fieldtype:"Section Break"}, + {fieldtype:"Column Break"}, + {fieldtype:"Column Break"}, + {fieldtype:"Select", fieldname:"item_group_2", options:["Products", "Services", "Raw Material", "Sub Assemblies"]}, + {fieldtype:"Column Break"}, + {fieldtype:"Select", fieldname:"item_uom_2", options:["Unit", "Nos", "Box", "Pair", "Kg", "Set", "Hour", "Minute"]}, + {fieldtype:"Section Break"}, {fieldtype:"Data", fieldname:"item_3", label:"Item 3", placeholder:"A Product or Service"}, {fieldtype:"Column Break"}, {fieldtype:"Attach", fieldname:"item_img_3", label:"Attach Image..."}, {fieldtype:"Section Break"}, + {fieldtype:"Column Break"}, + {fieldtype:"Column Break"}, + {fieldtype:"Select", fieldname:"item_group_3", options:["Products", "Services", "Raw Material", "Sub Assemblies"]}, + {fieldtype:"Column Break"}, + {fieldtype:"Select", fieldname:"item_uom_3", options:["Unit", "Nos", "Box", "Pair", "Kg", "Set", "Hour", "Minute"]}, + {fieldtype:"Section Break"}, {fieldtype:"Data", fieldname:"item_4", label:"Item 4", placeholder:"A Product or Service"}, {fieldtype:"Column Break"}, {fieldtype:"Attach", fieldname:"item_img_4", label:"Attach Image..."}, {fieldtype:"Section Break"}, + {fieldtype:"Column Break"}, + {fieldtype:"Column Break"}, + {fieldtype:"Select", fieldname:"item_group_4", options:["Products", "Services", "Raw Material", "Sub Assemblies"]}, + {fieldtype:"Column Break"}, + {fieldtype:"Select", fieldname:"item_uom_4", options:["Unit", "Nos", "Box", "Pair", "Kg", "Set", "Hour", "Minute"]}, + {fieldtype:"Section Break"}, {fieldtype:"Data", fieldname:"item_5", label:"Item 5", placeholder:"A Product or Service"}, {fieldtype:"Column Break"}, {fieldtype:"Attach", fieldname:"item_img_5", label:"Attach Image..."}, + {fieldtype:"Section Break"}, + {fieldtype:"Column Break"}, + {fieldtype:"Column Break"}, + {fieldtype:"Select", fieldname:"item_group_5", options:["Products", "Services", "Raw Material", "Sub Assemblies"]}, + {fieldtype:"Column Break"}, + {fieldtype:"Select", fieldname:"item_uom_5", options:["Unit", "Nos", "Box", "Pair", "Kg", "Set", "Hour", "Minute"]}, ], }, @@ -213,10 +243,44 @@ wn.pages['setup-wizard'].onload = function(wrapper) { "help": wn._("List a few products or services you buy from your suppliers or vendors. If these are same as your products, then do not add them."), "fields": [ {fieldtype:"Data", fieldname:"item_buy_1", label:"Item 1", placeholder:"A Product or Service"}, + {fieldtype:"Section Break"}, + {fieldtype:"Column Break"}, + {fieldtype:"Column Break"}, + {fieldtype:"Select", fieldname:"item_buy_group_1", options:["Raw Material", "Consumable", "Sub Assemblies", "Services", "Products"]}, + {fieldtype:"Column Break"}, + {fieldtype:"Select", fieldname:"item_buy_uom_1", options:["Unit", "Nos", "Box", "Pair", "Kg", "Set", "Hour", "Minute"]}, + {fieldtype:"Section Break"}, {fieldtype:"Data", fieldname:"item_buy_2", label:"Item 2", placeholder:"A Product or Service"}, + {fieldtype:"Section Break"}, + {fieldtype:"Column Break"}, + {fieldtype:"Column Break"}, + {fieldtype:"Select", fieldname:"item_buy_group_2", options:["Raw Material", "Consumable", "Sub Assemblies", "Services", "Products"]}, + {fieldtype:"Column Break"}, + {fieldtype:"Select", fieldname:"item_buy_uom_2", options:["Unit", "Nos", "Box", "Pair", "Kg", "Set", "Hour", "Minute"]}, + {fieldtype:"Section Break"}, {fieldtype:"Data", fieldname:"item_buy_3", label:"Item 3", placeholder:"A Product or Service"}, + {fieldtype:"Section Break"}, + {fieldtype:"Column Break"}, + {fieldtype:"Column Break"}, + {fieldtype:"Select", fieldname:"item_buy_group_3", options:["Raw Material", "Consumable", "Sub Assemblies", "Services", "Products"]}, + {fieldtype:"Column Break"}, + {fieldtype:"Select", fieldname:"item_buy_uom_3", options:["Unit", "Nos", "Box", "Pair", "Kg", "Set", "Hour", "Minute"]}, + {fieldtype:"Section Break"}, {fieldtype:"Data", fieldname:"item_buy_4", label:"Item 4", placeholder:"A Product or Service"}, + {fieldtype:"Section Break"}, + {fieldtype:"Column Break"}, + {fieldtype:"Column Break"}, + {fieldtype:"Select", fieldname:"item_buy_group_4", options:["Raw Material", "Consumable", "Sub Assemblies", "Services", "Products"]}, + {fieldtype:"Column Break"}, + {fieldtype:"Select", fieldname:"item_buy_uom_4", options:["Unit", "Nos", "Box", "Pair", "Kg", "Set", "Hour", "Minute"]}, + {fieldtype:"Section Break"}, {fieldtype:"Data", fieldname:"item_buy_5", label:"Item 5", placeholder:"A Product or Service"}, + {fieldtype:"Section Break"}, + {fieldtype:"Column Break"}, + {fieldtype:"Column Break"}, + {fieldtype:"Select", fieldname:"item_buy_group_5", options:["Raw Material", "Consumable", "Sub Assemblies", "Services", "Products"]}, + {fieldtype:"Column Break"}, + {fieldtype:"Select", fieldname:"item_buy_uom_5", options:["Unit", "Nos", "Box", "Pair", "Kg", "Set", "Hour", "Minute"]}, ], }, @@ -327,7 +391,7 @@ wn.wiz.Wizard = Class.extend({ }, show: function(id) { if(!this.welcomed) { - wn.set_route(this.wiz.page_name); + wn.set_route(this.page_name); return; } id = cint(id); diff --git a/setup/page/setup_wizard/setup_wizard.py b/setup/page/setup_wizard/setup_wizard.py index 714df2ec0fa..12767639c84 100644 --- a/setup/page/setup_wizard/setup_wizard.py +++ b/setup/page/setup_wizard/setup_wizard.py @@ -27,6 +27,7 @@ def setup_account(args=None): create_price_lists(args) create_feed_and_todo() create_email_digest() + create_letter_head(args) create_taxes(args) create_items(args) create_customers(args) @@ -234,16 +235,17 @@ def create_items(args): for i in xrange(1,6): item = args.get("item_" + str(i)) if item: + item_group = args.get("item_group_" + str(i)) webnotes.bean({ "doctype":"Item", "item_code": item, "item_name": item, "description": item, "is_sales_item": "Yes", - "is_stock_item": "Yes", - "item_group":"Products", - "stock_uom": "Unit", - "default_warehouse": "Finished Goods - " + args.get("company_abbr") + "is_stock_item": item_group!="Services" and "Yes" or "No", + "item_group": item_group, + "stock_uom": args.get("item_uom_" + str(i)), + "default_warehouse": item_group!="Service" and ("Finished Goods - " + args.get("company_abbr")) or "" }).insert() if args.get("item_img_" + str(i)): @@ -254,16 +256,17 @@ def create_items(args): for i in xrange(1,6): item = args.get("item_buy_" + str(i)) if item: + item_group = args.get("item_buy_group_" + str(i)) webnotes.bean({ "doctype":"Item", "item_code": item, "item_name": item, "description": item, "is_sales_item": "No", - "is_stock_item": "Yes", - "item_group":"Raw Material", - "stock_uom": "Unit", - "default_warehouse": "Stores - " + args.get("company_abbr") + "is_stock_item": item_group!="Services" and "Yes" or "No", + "item_group": item_group, + "stock_uom": args.get("item_buy_uom_" + str(i)), + "default_warehouse": item_group!="Service" and ("Stores - " + args.get("company_abbr")) or "" }).insert() if args.get("item_img_" + str(i)): @@ -314,20 +317,20 @@ def create_suppliers(args): "last_name": len(contact) > 1 and contact[1] or "" }).insert() -def create_profile(user_email, user_fname, user_lname, pwd=None): - pr = webnotes.doc('Profile') - pr.first_name = user_fname - pr.last_name = user_lname - pr.name = pr.email = user_email - pr.enabled = 1 - pr.save(1) - if pwd: - webnotes.conn.sql("""insert into __Auth (user, `password`) - values (%s, password(%s)) - on duplicate key update `password`=password(%s)""", - (user_email, pwd, pwd)) - - add_all_roles_to(pr.name) + +def create_letter_head(args): + if args.get("attach_letterhead"): + lh = webnotes.bean({ + "doctype":"Letter Head", + "letter_head_name": "Standard", + "is_default": 1 + }).insert() + + filename, filetype, content = args.get("attach_letterhead").split(",") + fileurl = save_file(filename, content, "Letter Head", "Standard", decode=True).file_name + webnotes.conn.set_value("Letter Head", "Standard", "content", "" % fileurl) + + def add_all_roles_to(name): profile = webnotes.doc("Profile", name) diff --git a/setup/page/setup_wizard/test_setup_data.py b/setup/page/setup_wizard/test_setup_data.py index dcc6b0f5cba..b5b63598930 100644 --- a/setup/page/setup_wizard/test_setup_data.py +++ b/setup/page/setup_wizard/test_setup_data.py @@ -1,26 +1,53 @@ + args = { - "attach_letterhead": "erpnext.jpg,data:image/jpeg;base64,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WVpjZGVmZ2hpanN0dXZ3eHl6goOEhYaHiImKkpOUlZaXmJmaoqOkpaanqKmqsrO0tba3uLm6wsPExcbHyMnK0tPU1dbX2Nna4uPk5ebn6Onq8vP09fb3+Pn6/9oADAMBAAIRAxEAPwD+/igAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgBGZVBZmCgAsxYgAKvLMSeAAOSTwO9AHxV4x/4KU/8E6Ph5rl74Y+IH7ff7FPgbxLps8ttqPh7xj+1R8C/DOuWFzA2ya3vdJ1rx3ZX9rPC/ySxT28ckbHa6g8UAcv/wAPYf8Agln/ANJK/wBgH/xMj9nX8f8Amo1ACf8AD2H/AIJZf9JLP2AP/EyP2de//dRu+f1oAX/h7D/wSz/6SV/sA/8AiZH7Ov8A88agA/4ew/8ABLP/AKSV/sA/+Jkfs7f/ADxqAD/h7D/wSz7/APBSv9gH/wATI/Z1/wDnjUAH/D2H/gln/wBJK/2AeOv/ABmR+zrx/wCZGoAP+HsP/BLP/pJX+wD/AOJkfs6//PGoA+hvg1+1N+zH+0al7J+z3+0b8B/jummxLcai/wAGvi98PviglhA7KqTXreCPEOuC1idnVVknKIzMoDEsMgHvHXmgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAQkKCx6AEn6Dk0Af5wP/B1n/wAFovjN4n/aI8a/8E0v2evHOs+APgv8I7LRtO/aI1jwfqt7pGs/GL4ka/olh4ivPAmra1YPbXx+HHgDSdW03StS8L2s9taeI/Gs2vt4ni1Wz0LQIbUA/iMbnOV/75VRnkf3QM/U89SeaAGjrnB6senXI/yPegAHB6HkL+HH+c/jQApJOcqeAR9ckd/8+tAC55xg9euPf/Jz/wDroARuexPH/sw4/HH5c80AGfvHDc+31/yT7/mAL3A56k5xx/F/n/8AXQB6F8Kfi18TfgZ4/wDDHxU+Dvjvxb8MviN4N1ODV/C/jbwNruoeGfE+h39vIHjnsNY0qa3uowwXy7i3leW0u4Ge2vLe4tpZYmAP9ef/AIN/v+CpWs/8FUP2FdM+JXxLTS7b9oX4P+Kp/g98dl0i1i03T/EviPTdG0zW/DvxM03R7eNLXSbP4heG9St77UdPsUt9MsvGGm+LLPRrKz0a3sLaIA/cmgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgBCMgg9Dwfcd/wA6AP8AFM/4LVzzXH/BWv8A4KLvPI8rr+2J8d4VZzkiK28a6hbW8YP92GCGKJB/CiKO1AH5gc4P178Dkr1B555+vP8AeoAQZz/30Oo3Hjue+P0oAXn+R65PQc8fr/eHSgA556dPoOvcdc46n8KADnrjv3Pqf5eg659aAA5//Wf9rv6jB/DJHegBOfm6Z4789O/9emRmgBecj6nvx1bt6/5NABzx069zk/e556env2oA/wBDj/gx5mmf4Yf8FErdpGMEPjv9mqeKInKRzT+GPi/FPIo7PLHbQI57rEg/hoA/u7oAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKAP8AFF/4LS/8paf+CjPr/wANkfH3/wBTvVPf/wDX60AfmMc4Of8A638PU8H1/wA4oAQZyPXLc8dcc9+oP4GgAGc47kLnt0A98nvnj/64ApyScjsR147d+OvvjjmgAyc49we3r9c/Q9c8HrQAN7+/6sMDr7df60AHPzevGenp356EfzPXFABzkdcZPp1+b3z/AJ9aADnAHvknj+96e/8AkmgD/Q0/4Md/+Sb/APBRf/sdf2ZP/Ub+M1AH939ABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQB/ijf8ABaX/AJS0/wDBRn/s8j4+8/8Ac+ap3/zzQB+Y3+Prx1Ht/TqT60AIM+p/i53c+nPH5dcGgBec9+MdT+PoefXnoe+RQAvPX29ePr06/gaADBz1PXPX8x06fj+XWgBDn3/P1P8AnHXjIoAOeRz25z/9bvxnPqT9QA7g5PUjrx3P+fT8KADkfn1J56/5789OtAH+hn/wY7/8k3/4KL/9jr+zJ/6jfxmoA/u/oAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKAP8UX/AILS/wDKWn/gozxn/jMj4+9s/wDM+ap+fNAH5jEdeP8Ax0H+76/j+vpQAgHPT1/g/L3/AK9jQAd+hxx/APxoAO7cHv8AwD1/X/JoACOenf8AuZH59f8APFACkdePX+EH+L/D9OaAE7Hj0/gH4/8A1/060ALjnoOp/g7c9+n4/ie9ABj2/wDHPf8AT8e3PWgD/Q0/4Md/+Sb/APBRf/sdf2ZP/Ub+M3+fegD+7+gAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoA/xRf+C0v/KWn/goz/2eR8fffr481X/P55oA/Mc85P8AMH1HXuenP/6qAGjqOB1bnB75xn2Pbnp34NAC4Oc46Y7ZPAHTk/j+mTQAYPXA5z29wfm75/Dr3oAMHrhfXpz/ACz75657UABHt+nqwPPf/HnPNAAAeRgdeuODj/PPpk0AHcH/AGj2OepOeme/596ADHTgdR7H72eOvGPf1zQB/oaf8GO//JN/+Ci//Y6/syf+o38ZqAP7v6ACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKAMzWda0jw7pOp69r+qadomiaLp97q+saxq99a6ZpWk6VptvJeajqep6jfTQWWn6fY2sUtzeX15PDa2sEbzTyxxqWAB+H/AMUv+DlH/giz8JfE194T139trwp4k1bTbmW0vp/hl4A+LfxT8PRzRMysLXxf4D8C654U1WLKnFxo+s6hbE8CY9wDzP8A4io/+CIf/R2mu/8AiPH7RX/zsqAD/iKj/wCCIf8A0dprv/iPH7RX/wA7KgA/4io/+CIf/R2mu/8AiPH7RX/zsqAD/iKj/wCCIf8A0dprv/iPH7RX/wA7KgA/4io/+CIf/R2mu/8AiPH7RX/zsqAP8xH/AIKa/Gj4d/tF/wDBQn9s747/AAi1yTxN8MPi7+0n8XPiF4B8QTaVquhzaz4U8U+LL/VNE1J9H12007WdNa7sp45WstTsbS+t9xjubeGUFFAPho55+uc8e3v25/TnPUATJz27+mef+Bfn/XrQADIPYZx6c8fX/H+VAC5OfpnnjPb/AGvz6dqADJz/APqzj/vr8KAA5/rzj1Hv6fTmgBMnnp79P1+b+Z/+sALzkfU+nqff8+M9evQgCZP689P73+91/rn6gA/sV/4NaP8AgrL+wp/wTU8E/tm6P+2L8YNQ+F+o/FzxR8DtR8BwWXw3+JPjwazZ+C9F+Jdn4ilkl8BeFvEcWmmyuPEOkxqmpvaPdfaS9os6wzmIA/q//wCIqP8A4Ih/9Haa7/4jx+0V/wDOyoAP+IqP/giH/wBHaa7/AOI8ftFf/OyoAP8AiKj/AOCIf/R2mu/+I8ftFf8AzsqAD/iKj/4Ih/8AR2mu/wDiPH7RX/zsqAD/AIio/wDgiH/0dprv/iPH7RX/AM7KgD9Bf2O/+Ct3/BOn9vbWn8K/srftVfDn4l+N47O4v2+Hdx/b3gb4kS2VnE09/faf4B+IWj+FvFWtWGnwr5t/qGh6ZqdnZIQ91PEvzUAfo0CCAQcg8gjkEHuD3zQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQB/nWf8HiP/AAU2+KV78bPDP/BNL4aeJdU8LfCrwf4I8KfE39oO20e9udPm+JXjjxqJtZ8D+CfExt5EbUPBngnwpBpPi2LRJJDpWs+KfE9rqGr2N1deE9BltQD+GIsxxyxxwBvYAAdABngY6AdOBgdgBNxPdugP3m9/f/8AX3oANx9W7j7zYz83+HXH9MgBuOerf99H0z6/565oAAxI6nPPBdux/wA8/hQAbjjOW7fxNzkD3/zz60AJnJHBzzySeuM89Tz7/hkckAU9DkZH69R/nrQA3uOOct3PXH9aAAdeh/h55x2x75/ycc0AKe+fQ/Xtn/J70AKfcdxzn34/Xr7d6AEb3GevTOcZH/66AD+9x2Gffg9P1/zmgA9OO579+efx/rQAcenf1/2hn3680AKCR0yM57kZ5/yc9s8daAAs2T9/1+82D+v8s0AAY8ct1PVjnOM+v88evegA3Hj7/J/vNn69env/AJIABj1yevdm74/x+n55AAbj6t1P8ROeM/59DQB0/gvxv4v+HXi3w3488B+J/EPgzxp4P1iw8Q+FfFvhfV7/AEPxL4a13S7qK807WtB1vTZ7fUdJ1XT7qKK5tL2yuIZ4Zo0bdtBVgD/ZL/4IW/8ABQDxJ/wUk/4Jw/Bf9oL4hC0b4v6TP4g+EfxqudPt4rSx1X4lfDe5ttOvvFEFrbpFaWb+OfD174b8b3unWNvb6fpmpeIb7TtPgjsrWBQAfr/QAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAIeh+hoA/yKv8Ag6jZm/4LdftZbmZtuhfs8KuWJ2r/AMM8fDYhVznaoJJwOMknqSaAP549vuR9D/n6fSgBMZ7noDkHnv8Az6k9zzQAY57+n3h/tc/X09PwNABjJ79v4gf4Tz9ff8aAADp1HB6EevX684z6cUAAX6jp0PsP8/me9ABjkDk8nksM9B+P+HXvQAEcH8uoHofw/wDrn1oAQDnv1P8AED+P1/UdTQAoGSeT0HcHPHf/AOv1oAUjryehPXGMenp6Z7CgAI9z16Z45PT6e34UAIw6+49QO49fyz6cUAGPvcnIxzuGeh/L8aAFwMj6njIx359z+o/CgBMe56+o556n1P8A+qgBcc/Xd3756/Xnr26UANI5br0/vD8sdh9aAFA6devqD2z+OO350AJjgcnr/eHHXke/60AOx15J5A5PXOOv+HfJ9aAEIxnr3zlhz8vf/PHXvQAMMA8k8dz7j/H+negD/UY/4My2Y/8ABKv4nKWYqn7anxYCgkkKD8LfggxCgnABYknHUkk8mgD+tugAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgBryJGu6R1Rc43OwVcnoMsQMn60AQ/a7X/n5t/+/wBH/wDFUASpLFKCY5EkAOCUdXAPuVJwaAH0AFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAIeh+hoA/yKP8Ag6i/5Tdftaf9gP8AZ4/9Z4+GtAH88xOPT8c+o9Pr/nmgBAfp0X9Sfy68UANz349fb+P8f896AFH3u3UdP90/pQAKcAdOh6/X1/z2oAP4Tz6d/ZfrQAmeQeD9768Dvx1/DpQArHgj/wDX1X/H+XvQAgPPbq/8gev9fSgBVBYnAzwp4GfTnGP8P8ACQo5/hPQ/wnqfw6f55oANkn909R2PT8uv+fegBGSQj7p/75P94Y7Ht1oAjz9/p2/PGD/k/j3oAdnkf7zHrz/F2/rQAdu3Xt/vf5+vWgAz9P4zz9f5etADT95/93/D/PvQAo7dP69Pp+vpjk55AEB4X6j+bD/PfPNACg8dQef6r7cnnr/kACHv/wAC7eigfh/kc9aABiSD9AenqR3/AM59BQB/qL/8GZX/ACis+KH/AGer8V//AFVfwPoA/rdoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoA/gT/AOD2b9sfyNO/ZL/YJ8OariS/n1f9qP4rafDNtcWloNa+Gnwct7gRNmSC6upfi5qF3ZXWEE+m6BfLFI6QSxAH+fnQB/ow/wDBj/8A8m9/t6/9ll+Dv/qEeLKAP7l6ACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKAEPQ/Q0Af5FP8AwdQ5/wCH3X7Wn/YD/Z474/5t4+Gv+f1oA/nkP+P8WO/19z/KgBPc56L/ABEdc5PX+f8AWgAznHX6bj/te/PQc5/KgA6nqeo/iPPyk+v455z60AA6dznPfnr9R+J/x5ADPGec8dWxngH6f40AGeRyTkt0bPb1z179eP1oAUnr/wDFf7v+PP8A9egBM8jr1Yfez0H16/j+fWgD+rb/AINMP2QP2Yv2x/2v/wBpXwR+1H8Dvh38dPCnhj9miLxV4d0H4jaFHr+naN4i/wCFr+DNIOsWFvLIghv20u+u7Ezqd5t55I87HdWAP72v+HFf/BIP/pHj+y5/4bi1/wDkqgA/4cV/8Eg/+keP7Ln/AIbi1/8AkqgA/wCHFv8AwSDUq3/DvD9lw4ZeP+Fb2hz8w7Ncsp+jBge4IyCAf41/xY02w0f4ofEfStLtILDTdM8eeMtP0+xtgYrazsrLxPq1paWsCbjshtraGKCJSxKxxquTjNAHAdx16nvxxn39vSgA7Z5646n+9j1oAPU8/wAX8R7HHr/+r1oAQnluvT+9+PH6nvigBR269f72e2eeeen09qAGgjjJP/fZ9+v+e9AC5z+fqT3Xvn3P8vXIAmev/Au5OflHvz685xQAN0P0B+8T1P4/iaAP9Rf/AIMyv+UVnxQ/7PV+K/8A6qv4H0Af1u0AFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAf4rX/AAWx/bG/4br/AOCnn7Wfx703Vf7W8CP8R734bfCaeKbztPf4V/CaKP4feDdT0xQzLBa+LLPQZPHM8KMR/afijUJiS8rGgD8rKAP9GH/gx/8A+Te/29f+yy/B3/1CPFlAH9y9ABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFACHofoaAP8ij/g6i/5Tdftaf8AYD/Z4/8AWePhrQB/PKQT39ewPfP+H8z7ACDJ/JT0+v4Z/wA+9ACdx07g8f73Ufn0989qAD+L8s/XaevPXr04980AKBkD6Htnv7/oPxPSgBP4eo7ZyM9h1/8A1Ht70AHpznO7n6j2yOvX1P40AK3Q5/Hj6fn09fY9KAGgc9c8t24zjn+mentnrQB/aT/wZNf8n1ftZf8AZpMX/q6PANAH+lZQAUANbp/wJP8A0NaAP8Fz418/GD4rf9lI8eZ4z/zN2te9AHmOOQeOrdv949f88880AHPH1x04+99f/r+/NAC//Zds9/f+XfmgBpHzNz2547e/6dMn6UAKOq++T09u3oD+B9aAE+bjn6cDPQ//AF+p9e/UAB+HX0Hcp/jQAdOM/wB78flB5/r1yefegBCCM5Pb+o9+np+PTuAf6jH/AAZlf8orPih/2er8V/8A1VfwPoA/rdoAKACgAoAKACgAoAKACgAoAKACgAoA4j4gfEz4b/Cfw9c+L/in8QfBHw08J2eftnij4geK9B8G+HrXClz9p1rxHf6bpsGEVnPm3K4UFjwCaAPzC+Iv/Bev/gjn8Lrh7XxN/wAFC/2dtSljdo3Pw88S6h8Xody5ztufhNpPjW2deDh0mZD2Y5GQDxSL/g5q/wCCHE121kv7d2gCZSMvL8EP2m4LQ5JHy383wVjsX6clbkgdTgEEgH0p8LP+C3P/AASR+M11ZWPgb/goP+zGL/UXWKw0/wAa/EbTfhZqN3PJxHbQWHxRHg68ku5WISG0WE3MshEccTSEKQD9MfD3iTw74v0ex8ReE9f0XxR4f1OLz9N13w9qtjrWj6hASQJrHU9NnubK7iJBHmQTyISCN2RQBtUAFABQAUAFADSyjqy59yKADev95f8AvoUAKCDyCD9DmgBaACgDkvHHj7wL8MvDOpeNfiT418JfD3wdo0ay6v4t8ceI9H8J+GdKidgiSalr2vXlhpdjG7kIr3V3ErMQoJJxQB+T/wASv+Dgj/gjN8J9UvNH8U/8FA/ghqV5YErcP8OD4x+MmnMylgRa6z8IfCvjnSL4gqQRY31wen94ZAOB0T/g5S/4Ih+IJYYrD9vTwZbvO6Ih1z4WftA+GYlZyFBmn8SfCXSYbdAT88lxJFHGMs7KoJAB+nv7N37X/wCy3+2H4Z1fxh+y38fvhV8evDvh69tNN8R6h8MfGWjeKW8Nalf2z3ljp/iSy0+5l1Dw9f3trHJc2tnrNrZXFxDFLJDG6xSFQD6NJA5JA9ycUAJvX+8v/fQoAN6/3l/76FADqACgBkkkcUbyyukcUaNJJJIwSOONAWd3diFVFUFmZiAoBJOBQB+cvxr/AOCv3/BLz9ni91HSfi3+3l+zF4e1/SJHh1bwtpfxV8N+N/GOlzx/ft9S8HeA7vxN4osbkdre60iKZuqoc0AfIM//AAcy/wDBDu2vVsJP27/DjTsSBJB8Fv2lrqy4OPm1K2+DM2nJ14LXQB5IyATQB9FfCX/guB/wSP8AjbeWmn+Av+Cgn7NQ1G/nS2sdO8c+PLf4Taje3UjbIrWzsPivB4Ku7q6nchILeCGSad2VIUdmUEA/T7Rta0fxFpdjrnh/VtM13RNUt0vNM1jRr+11TS9RtJRmO6sdQspZ7S7t5Byk9vNJG45VjQBp0AFABQAUAFADd6/3l/76FABvX+8v/fQoAcCDyDn3BzQAUAFAHh/xr/ab/Zv/AGbNJh179oj4/fBf4E6Ncqz2mp/GD4n+CvhvZ320suywm8X63pC38rOpjjhszPNLL+6jR5CFIB+YvjL/AIOK/wDgir4EvrnT9b/b9+Fd9PakiWTwb4b+KvxFsnIJH+jan8Pvh/4n028HBw1pdzqRggkEZAKPhj/g48/4Im+LSg0r9vn4c2nmEBf+En8DfGjwUBnp5h8Z/DTQREPUylAOpIoA+8/gH/wUL/YU/alnhsf2d/2vf2dfi/rM8nlp4Y8E/FvwVqvjFXJwon8GLq6eK7YSnPkNc6PEs4BMJkAJAB9i0AFABQAUAFABQAUAFABQB8tfHX9uH9jP9mF2t/2iv2rP2ePgjfhd6aP8T/jD4B8G+ILrKeYFsfD2ua9Z65qMpjzIsNjp9xKyAuEKgmgD86vE/wDwcff8ETfCN1cWeq/t8/Du7mtWKyP4Y8CfGrxtasR1Nvf+DPhnr9jeL6PaXE6t2Y0AUfD3/Byf/wAERfE1xBbab+3r4JtpLlwkbeIfhh8ffCVurN0Nxd+K/hPotrap6yXU0Ma/xMKAP0A+Bn/BRD9g39pm6t9O+AP7Y37Nfxa1u5dI4vDPgv4y+A9W8X+ZLjykl8Hx64PFEDSk7YhPpMZlYMqbmVgAD7IoAKACgAoAQso6sAfcgUAJvX+8v/fQoAN6/wB5f++hQAoIPQg+uDmgBaACgAoAKACgAJA5Jx7k0AN3r/eX/voUAG9f7y/99CgA3r/eX/voUAOoA/Hb/gut+3t4T/YF/wCCbn7Snj0ePPD/AIa+Nfjr4a6/8MvgB4cn8Qadp/jPX/iF8Qhb+B4PEHg3RZ7qHUtal+Glp4jn+ImryWME8Gn6d4bllvCokijmAP8AGQoAKAP9GD/gyAIH7Pf7euSBn4y/B3qcf8yR4s9aAP7lt6/3l/76FABvX+8v/fQoAN6/3l/76FADgQeQc+4OaACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKAEPQ/Q0Af5FP/B1AM/8ABbv9rTqf+JH+zx0/7N4+GvrQB/PKefX8CPX60AJj69vTt/nnPXtQAY/3vzH+1+vP8vegAxznnt3HoR9e/PvQAYwOM9/TPX8v/rZ70AGOCOe3pnjH+H86ADHs3Ge47/j+Xv19aAAjOc5P/wCsep9v5nuKADHf5s5J7dSP849+tAH9o3/Bk1/yfV+1l/2aTF/6ujwDQB/pWUAFADW6f8CT/wBDWgD/AAXPjVz8YPit1/5KR486df8Akb9a9aAPM8c9+pPbGTn8e9ABjjv1z2z1z/n296ADH179/U5/P0/WgBCOSeeeO39aAADp14+npjnk/pQAY6deMdx6H39+ffHagBMYx169yPY/0/IHvigAxnqG5z6dx9fbAznnrQAEZByDnHXjsc+p59fXtQB/qLf8GZX/ACis+KH/AGer8V//AFVfwPoA/rdoAKACgAoAKACgAoAKACgAoAKAPm/9q39rr9nP9iL4NeIvj7+1D8U/Dvwm+GHhwx282ta5JPPf6zq9xHNJYeGvCXh7TYbzX/F/irU1t520/wAOeHNN1LVrmG3u7sWq2VleXMAB/nqf8FKf+Dw39qL406n4j+HH/BPLwtD+zB8KPPuLC1+MfjDTdF8WftBeK9PBMf2+w029Gs+APhZbX8LyobGys/G3ii0222oab430a7MlpCAfyNfGX48/G79orxld/EP4+fF74lfGjx1fbxceLfij428R+OtfMTuZPssWp+JdR1K6trGNji3sLaSGyto1SG3giijRFAPJ6ACgAoA+nf2aP20/2tP2N/E0fi79lv8AaJ+LfwN1f7ZDfXsPw/8AGmsaPoGvTW5QxxeLPCIuJfCfjGx/dxiTTPFWi6xps4jRZrSRUUAA/tk/4Ja/8HjlzqGr+Hfg/wD8FS/B+mWltf3FlpNh+1f8I/Dz2VtYPK0cJ1D4x/CfTDPELQyNLcah4q+FVtbpZRiC2g+F8sf2rVYgD+8rwH4+8D/FPwZ4Z+Ivw18X+G/H3gHxno9n4g8JeM/B+taf4i8MeJdD1CITWWraJrmlXF1p2pWF1GQ0VzaXEsTcjduVgADraACgAoA/xbv+C7n/ACmG/wCCh/8A2cv44/8AQrSgD8mKAP7+f+DHn4uYk/4KC/Ae9uvvJ8Bfi54bst/TY3xI8G+Nbryyec+Z4Ai3oOMYkPMdAH9/9AH8f/8AwWm/4Oo/hL+xXrXin9mr9hay8I/tCftN6Fd6h4f8efEXWJLnUvgd8FdatWltL7R1bSL2xuPij8QtIuUeC/0XSNUsfCXhfUU+za9rur6xp2s+DYQD/O2/ax/bn/a6/bl8c3PxC/au+P8A8R/jTr0l9c32m2XirXrj/hEPCzXZbzbTwP4C077D4J8C6bhmA03wloGj2RLSSPA0sssjgHyhQAUAf6cf/BlX4C/sT/gm7+0L8QJ4fKuvHn7Y/inSreQrzc6L4J+EHwgjs5g/8SrrPiHxFbheQrQOc5cgAH0B/wAHgn/KHrVP+zl/gf8A+g+MKAP8pygAoA/3FP8AgmZ+0I37Vn/BPj9jT9oS5vv7S1r4m/s6/C7WfF92ZPOLeP7LwvYaH8RITNktK1p460vxDaNI+JHMBaREkLIoB+a3/BZv/g4S/Zl/4JQ6bcfDLRbOy/aB/bD1XTYLvR/gZoeupp+leAbLU7QXWl+KfjV4mtYNQfwrp1xbSwalo/hCztp/Gfiq0ms54bbQvD+pR+LbYA/zWf29P+Cyv/BRD/go3rGrn9oz9oPxQfh1qF7Pc6f8CPh1c3XgD4IaJavIz2tgvgXRLtY/FJ05WeGy1z4hX/jLxUsTyJLr8yyOCAfl1QAUAFAH2r+x7/wUX/ba/YI8TweJ/wBk79o74lfCNRqEWpap4Q0vW5NU+Gnie4iZCf8AhL/hhr66p4C8T7408jz9Z8P3d5bxPJ9jubaRvMAB/oZ/8EYf+DqP4N/tv6/4U/Zs/ba0nwr+zl+094hu7LQPA/jfR7i7tPgT8Z9dudkFno1rPrd7fX/wv8eavcsLbS/DniDVtV8N+JL8x2eheKbbXdV0jwhKAf14UAFABQAUAf4N/wC0h/ycR8ev+y0fFL/1ONdoA8XoA/0sv+DKT9oT/hNP2Jv2of2bb+++06n8CP2gNK8f6XBJJ+8sfBvx08Hw29jYwRk/8eqeLvhX431JmUEi61mYSNhohQB/Tp+3Z/wUD/ZX/wCCcXwT1H47ftV/Emy8E+Gla5sfCnhuzSPVviD8TPEkFv8AaIvCPw48IxzwX3iTXZw0RuH8y00TQraYat4o1nQtEiudTgAP84j/AIKPf8HZv7fn7WOq614N/ZRvp/2IvgZIbuytf+EF1C21b49+KLByY477xH8W5bGG58G3MqpHeWun/Cuz8LX+jyzT2F34v8UwpHdsAfy5+LvGPi7x/wCItU8X+O/FXiPxt4s1y5e91rxR4u1zU/EniLWLyU5ku9U1vWbq91LULmQkl57u5mlcnLOTQBzlABQAqsyMrqxVlIZWUkMrA5DKRyCDyCDkHkUAftV/wT+/4OAf+CmP/BPC70zR/h18cNQ+Lfwfs5o/tPwJ/aAm1X4l/D4WYcGS28MXt7qlr42+How08sUPgTxVoOky30xvNW0jVyDE4B/pS/8ABIT/AILh/sqf8Fa/h8kHgu+g+FX7TPhfRor/AOKH7NninWLa48S6XHF5UN74r+HuqNFYp8Rvh2buRIv7d02ytdX0GSeztPGGg6BNqGkPqgB+1FABQAUAFABQB+Ev/BW3/g4B/Yz/AOCU1jf+BdfvJvjr+1Vc6TFqHh/9nLwBqtrb6hpC39v9o0vVPi54ya31LTPhfoV5C0NzbW9zY63421SyurPUdF8Gaho88urWwB/nfft4/wDBxv8A8FSP27NT1vTdQ+O2r/s6/CPUvPtrT4N/s13+r/DPRP7KlLo1n4n8Z2Gov8SPG73tr5UWsW2v+LJfDV5Ksslh4Y0i2uJLMAH4UXFxPdzz3V1PNc3NzNJcXNzcSPNPcTzO0k0880jNJLNLIzSSSSMzu7MzMWJJAIaACgBQSpDKSGBBBBIIIOQQRyCDyD1zQB+y/wCwv/wX1/4Kg/sCajpNr8NP2jfEvxO+GWnG3hl+CH7QV7q/xb+GUumW5BTS9Fg13VU8WeAbQctj4b+KvCBkkYtdfakZ4nAP9D7/AIJBf8HG/wCyH/wVGl0n4SeIoF/Zq/a4ks0z8F/GmvWd74e+I91BC0l/c/BPxzJFpsXi2WKNGvbjwXq2naJ44srb7XLYaX4k0fSNR8RKAf0RUAFAH8e3/B1v/wAEcf8Ahrb4Ev8At9/s/wDhX7X+0h+zX4UnX4r6Bolnu1P4v/s/6R9p1LULsW8CF9S8ZfCAS33iLSmAW91bwPP4o0YvqV9pHg7S4wD/ADEKACgD9Qf+CQf/AAUq8ff8Esf21vh5+0f4c/tPWfh1eOvgX4+/D6xnCr8Qfg7r99Zt4jsLeCWWG2bxN4cntrPxh4JuZpreOHxRoWnWt7cDRb/V7a6AP9nr4WfFDwD8bfhr4D+MHwr8T6Z41+G3xN8JaD458DeLNGlM2m+IPC/ibTbfVtG1S1Z1SVFurK6id7e4jhurWXzLa7hhuYpYkAO9oAKACgAoA/zK/wDg7O/4K+/8NPfHdf8Agnl8CPFH2r4C/s1eKZbr4161o15nT/id+0LpiXOn3Xh95oHZb7wz8F0nvtBWFmS3vPiJeeKJ7m1u08LeFtUAB/G3QAUAf1Pf8G5H/BO74L+IPEniv/grJ/wUC1/wr8MP2D/2LfEGnXvh3W/iZItj4S+J/wAfbW801vDdr9nmimm8R6D8O9U1HQ9QbRNOtry68ZfEfU/BPgzS7HxCF8VaGgB+pv8AwU0/4PKr+7/4SD4V/wDBLv4eHTYD9q06T9qb41+H4ptQkHzxDU/hZ8GtQEtpaDcEutM8QfFb7bJLFJJban8LLOZUuAAfw7fHf9oT44/tP/EjW/i9+0P8V/Hfxl+JfiF86p4y+IPiPUfEesPbpJJJb6bZS380sWk6JYebJFpWg6TFY6LpFsRaaZYWlqiQqAeO0AFABQAUAFABQB/rO/8ABpR/yha+Df8A2V39oD/1ZWq0Af0t0AFABQAUAFABQAUAFABQBy3jbxv4O+G3hHxH4++IPinw/wCCfBHhDRtQ8ReK/F3ivV7DQPDXhvQdKt3u9T1rXdb1Se107S9L0+1jkuLu+vbiKCCNSXfJAIB/Lb8ev+Dw7/glf8JvF2peFPh9oP7SX7RMGl3txZy+Nfhf8PfDOheBb5raZreWTRdQ+KXjfwR4h1W38xJDDfJ4Wt9PvIfLuLK6uIJUlIB4N/xGwf8ABPr/AKNc/bO/8FHwO/8Anu0AH/EbB/wT6/6Nc/bO/wDBR8Dv/nu0AH/EbB/wT6/6Nc/bO/8ABR8Dv/nu0AH/ABGwf8E+v+jXP2zv/BR8Dv8A57tAAf8Ag9g/4J9EH/jFz9s7/wAFPwO/+e6f60AfxB/8FlP25/hx/wAFHv8AgoT8bP2vPhP4S8ceCPAvxM034W2mkeG/iNFoMPi2xk8C/C7wl4F1J9Ri8M6vrujLHeanoF1d2C22q3TfYJoPtBjuPMjUA/L0j/d79R7/AP1+ff60AJ+XRevTvzjj8KAEHUdD/L+P9P59aAFHJ6dx29VPH/1qABeg6Hg9f971waAAdO3br/ujuQf5f40AHcdOrdBgHj8fx/KgAbgHp/nb/k/hQAg6jgdXH6d/zoA/tI/4Mmv+T6v2sv8As0mL/wBXR4BoA/0rKACgBrdP+BJ/6GtAH+C58a/+SwfFbp/yUjx4ef8Asb9aoA8y7j/ebnv/ABf560AHYcDr19Pm6f5//WAJ6/R/5nv/AJ60AIRy/Tt1Hr6e/wDM0AL3HTv268Dof5njPpQAmPu/d5x29j155/x/UAUfUde31Xvjr/X6cACevT+Lt/sj8vf3/OgAPQ9Og6Y9Rzn0OeM/p3AP7DP+CCv/AAcVfsrf8Eov2M/GH7N3xp+Cv7QvxC8XeIf2gPGnxbttd+Fll8N7rw5DofiXwZ8PPDlpps7eLfHXhnU11a3u/B9/PdrHYy2Zt7mzMN0ZRcRqAftp/wARsH/BPv8A6Nc/bO/8FHwP/wDnu0AH/EbB/wAE+v8Ao1z9s7/wUfA7/wCe7QAf8RsP/BPr/o139s7/AMFHwO/+e7QAf8RsH/BPr/o1z9s7/wAFHwO/+e7QA5f+D1//AIJ8l1D/ALL37Z6qWUMw0f4HsVUnDMF/4W8NxUZIXI3EYyM5oA/YD/gnZ/wcBf8ABOP/AIKV+LLf4X/Bv4i+Jfh58bL61lu9J+Cvx08PWngPxx4lhtYZbi+/4Qu9sNa8R+CvG15ZQQXN7caJ4b8VXviWHTLe41OXQksLe5uIQD9ss55ByDyD1znvQAUAFABQB8h/t1fttfA3/gnp+zJ8Rv2p/wBoPXX0vwP4CsFTT9F09raTxR4/8ZaissXhb4eeCdPup7dNU8V+Kb+M29nC80Nlp1lFqPiDW7vTvD2javqdkAf49f8AwVA/4Kk/tK/8FVP2hNW+NHx01250vwjpd1qNj8HPglpGqXlx8P8A4N+D7iZPK0jQbSUW8Wp+JNSgt7Ofxn44u7KDWfFuqQxySx6dolhoPh/RQD816ACgC9pumalrN7BpukaffarqN0xS10/TbS4vr25cKXKQWtrHLPMwRWYrHGxCqWPAJoA9avP2b/2iNP0lNfv/AIC/Gix0KUMYtbvPhb44ttJkCgMxTUptCSzcKCCxWY4BBPWgDxuaGW3llguIpIJ4JHhmhmRo5YZY2KSRSxuA8ckbhkdHAZWBVgCCKAI6ACgD+lX/AIN7f+C7Hj3/AIJk/Grw/wDA342+KtW1/wDYN+KniZbTxxoF8brV2+BXiPXZlgT4weArdfOvLHTLe9eGb4l+F9LSWDxDoJvtcsNLvPF2m6ct8Af6yGia3o/iXRtI8R+HdW03XvD+v6ZYa3oWuaNfW2p6RrOj6raxX2matpWpWcs1nqGm6jZTwXljfWk0ttd2s0U8EskUiuQDToAKAP8AFu/4Luf8phv+Ch//AGcv44/9CtKAPyYoA/q1/wCDOj4uf8K//wCCteoeAZ7rZa/Hb9mH4ueA7ezd8R3Gt+F9V8FfFuzuETI33Vpo3w88RRxnnbbXl7xzuUA/dP8A4Okv+C82ufs42esf8E4f2N/G93oXx08S6NbP+0z8WfDF61tq/wAJfBniTS473TvhZ4Q1W3YXOmfEbxrol/a6v4l8QWUkF54M8H32nWmj3B8R+Jpb7wiAf5vBJJJJJJJJJOSSeSSTyST1NACUAFABQB/rc/8ABqB4C/4Q3/gif+zxrbQ+TN8TviD+0D49mBXa8nkfGTxd8PreZwcH97ZeArV4mP37cwupKMpIB5T/AMHgn/KHrVP+zl/gf/6D4woA/wApygAoA/tS/wCCeP8AwcSeDv8Agn5/wQHu/gX4N16y1z9ubwR8YPix8Kv2ffAOpadc6jbeEvA3xDvI/ilF8dvEjXdpJod34X8HeIPHPjbTtD8O3FzdXeveMtL0jSbzRx4Vk1XUrQA/jd+IPxB8cfFfxz4t+JnxL8V6946+IPjzxBqnivxl4x8Ualc6x4h8S+I9bu5b/VdY1fU7ySW5vL6+u5pJppZXJy21QqKqgA4+gAoAKACgAoAUEqQykhgQQQSCCDkEEcgg8g9c0Af6V/8Awauf8FxvE/7WHh4f8E7v2sPFs3iH4+fDDwhcaz8Afih4i1OS58Q/GP4ZeG4l/tjwP4nvL52uNb+I3w20vytR0/V/PudU8XeALbUL7V4f7T8Ea1r3iIA/tIoAKACgD/Bv/aQ/5OI+PX/ZaPil/wCpxrtAHi9AH9IH/BtF/wAFRPgp/wAEwf2qf2hfGv7SnifVvD3wW+JP7Mfimxe20PQ9X8Q6rr3xW8BeItA8W/DjQtN07SbW6X+1fEGmjx14V0e61aTS9CtdV8R2U2ta7o+mrdXagH5kf8FMf+Ckf7QH/BUL9p3xX+0R8ctauodOa61DSPhL8L7W/muPCPwc+G/2+WfRvBfhq3KW8Et0sHk3PinxK1pb6l4u1/7TrGoLEjWdjYgH57UAFABQAUAFABQB7R+zt+0H8W/2U/jf8NP2ifgV4uvvA/xX+Evimx8W+DvEdid3kX1mXiudP1K0YiDVtA13TZ73QvEmhXqy6dr2galqWjalDPY31xC4B/s7f8Epv+CiHgT/AIKhfsUfC79q7wdpsXhnW9b+3+D/AIseAo7sXp+Hvxe8Ji2t/GXhiO53ySXGkz/a9O8UeE7q6KX974L8SeHL7Urez1G5urK3AP0aoAKACgD+U7/g48/4L7wf8E3vBsn7KH7Lmrabqn7bPxP8L/b9S8Sr9j1PT/2afAutxNFY+LtUsJhcW178T/Ets0tx8PPDOoQyWuk2Kp478TWsulv4Y0fxgAf5bPizxb4p8e+J/EHjbxx4k13xj4y8WaxqHiHxR4r8Uatf694j8R69q11Je6prWua1qk91qOq6rqN5NLdX1/fXM91dXEsk00ryOzEA56gAoA7bwh8NPiP8QZTD4C+H/jbxvMJfIMXhDwprviWUT4VvJMejWF64l2ujeWRvw6nGGBIBe8ZfCH4s/DkOfiF8L/iJ4ECOsbnxl4K8S+GAkjsERHOt6ZY7XdiFVThmYgAEmgDzugAoA0dI1fVvD+raXr2g6pqOia7omo2Wr6LrWkXtzpuraRq2m3MV7p2qaXqNnLDeWGo2F5DDd2V7aTRXNrcxRTwSxyxq4AP9R3/g2f8A+C7d/wD8FDPh7d/sjftW+LLO5/bM+EOg/wBo+GfFuoG3sbv9ov4WaXFBBN4ikVPKt7v4peCCY4fHdtbRQz+ItDmsPG9rBeTw+NptJAP6yqAGuiSI8ciLJHIrJIjqHR0cFWR1YFWVlJDKwIIJBBBoA/yeP+DmT/gjo/8AwTi/am/4Xv8ABTww1j+x3+1Dr+r6z4LtdMtWXSPg98VpRPrPjD4PSeSn2bTdDu1N14t+F8DC1R/C7ax4X0+C4HgC/v7kA/mQoAKAP7y/+DQj/gr1/wAI3rs//BK34+eKNmgeJ7vXPGH7IGv61ebYNI8Tzm613x78DluJ38uK08Ut/aPj3wFbt5Ea+JU8aaMs95qPirw3psQB/oW0AFABQB/PF/wcbf8ABXS2/wCCYn7G954Z+F/iCC2/a7/aWs9d8DfBCC1njbVPh9oaW0dt45+N1zBkm3Hgyy1C307wY04K3vxA1fQ7lbTVNJ0HxLDbgH+RXc3Nze3NxeXlxPd3l3PLc3V1cyyT3NzczyNLPcXE8rPLNPNK7SSyyO0kkjM7szMSQCCgD70/4JqfsAfFr/gph+198Mf2VfhNFNYv4ovTrfxG8cvZSXulfC74U6HcWr+NviDrKK0UTppVncw2GhafPc2a+IfF2q+HfDEN3b3WtQSqAf6MH/Bwx+zf8Jf2Q/8Ag3G+J/7NfwL8NQ+FPhX8H3/Zj8I+FNKQxyXc0Fr+0J8OZ9R1zW7yOKE6p4m8Tavcah4j8Ua1LGtxrXiHVdT1W5Hn3clAH+VXQAUAFABQAUAFABQAUAf6z3/BpT/yha+DP/ZXP2gP/Vl6tQB/S1QAUAFABQAUAFABQAUAFAH8BX/B6j+3B4/0HVP2bf8Agn34S1u70PwN4u8EP+0p8Y7GyuJbf/hOUXxlrngr4S6Dq5hmj+16B4d1zwZ438UT6PepPp994hi8L6s8JvfDdjJGAfwAMSx3HBJ5ZiWJJJPJOcknuTznjrgUAAx/s9+57j6n88/rQAgx146N3Oe/bP8AnmgAHX+HuOp649ckd/8A9RIyAHGO3Udzjoeeuf8APqDgAT/vn8z1/wC+v8ffGeAAP/AT+J/qf89enNADjg/3e/Un1J7Hv+f9ABDjnp0Xuefrz/8Aq7+tABxkdOh5yf8Aa9+nr/8AXoAXPP8AXPP3f979e+etAAMEduh6k46/Xj19/wA6ADII/LjJ9B2zn9D0oAOOOn8Xc4zj6+/P5jqMgCnHPQ/ie+3qc/rn+tADR1/h/i7nHTHr39+1AH9pH/Bkz/yfT+1l/wBmkRf+ro8A+tAH+lbQAUANbp/wJP8A0NaAP8Fv41/8lh+KvT/kpHjzgk8/8VfrXuP6/wBaAPMuNw6dT3Oc5Pv3/XPvQAnp06joT/ePbOTz7HvQAvHPTo3Un+99e/fue1ADT1bgdfU89ffr+H1xQA4fw9Ordz+nJx7g4PtQA38ufc+h6/N+H8+oBAFH4df9r1X1/wA5x2zQAfl/F3Pp9eff8x60AIcYPQ8DuT3Hv0/Ud+vIAdyeDwe/PT/eOf8APPoAKPvHp198/eHvj+ue2OoAccnj8zn7w7k9ffuehPNACDtwPfk9j67v54/GgBR34H6+jdyf1zjrzQAh7fd6epHc+pH60AdB4V8T+IvBXiTw/wCL/CGu6r4X8VeFtb0jxJ4Z8SaFf3el634d8R6Hfw6lomv6LqljNBe6bq+jalbW+o6bqFpNDd2l1bxSwyoy0Af7Xn/BI/8Aa5179uz/AIJvfskftUeLhbf8Jt8T/hiIfH89lBFa2d/8RPAPiPXvhn8QNWtLOEmKytdY8Z+Ddc1W3sYzssobxLVeIqAP0ZoAKACgD/Jd/wCDm7/gq3qX/BQf9t7W/gz8OPEU8/7LH7Iuu+Ivhx8P7SwvWfRfiF8TLG7fSfiZ8XZ44JHtNSivNVsZPCPgS98y7t08FaLFrmlNYy+NNdgmAP5qaACgD+0L/ghN/wAGtt9+2D4L8Jftff8ABQaTxX4C/Z38W6fp/iP4PfA7w1qTeG/iF8ZdAuzHd2PjPxtriQy6l4D+GOuWWG8P2Ojmx8deM9Ou18Q2GreENCGh6n4qAP8AQe/Zw/Yz/ZP/AGQfDdt4T/Zi/Z2+EHwO0i3sINNmk+HngbQdC1zWLe3RESXxP4qgsz4o8XahJ5aPdav4o1jV9VvZVE15ezzfOQD6YoA+B/2xv+CX37BX7e3hvW9C/af/AGZfhf4+1fWbVreL4lW3hyw8M/GLQpVTFteeHviz4ch03x3pkltKsU5sRrc2i6gYIrbWdL1Ow8y0kAP8zP8A4Ltf8G/vxR/4JNeJrb4ufDTWNb+MH7FHjrxFFoHhL4h6tHZt46+GPibUILm7sPAHxct9Ks7DTpZ76CzvP+EZ8eaPp9hoPiQ2stlfaZ4b1trLTNRAP5y6ACgD/Sb/AODOf/gpXrHxs+BPxL/4J6fFrxbda346/ZttLb4gfAWTWr03Op3n7P8ArV7a6Nr3gyyllZ7mfTvhN42u9NOnC4kkay0D4jaLoGmLDo3hm1trUA/tdoAKAP8AFu/4Luf8phv+Ch//AGcv44/9CtKAPyYoA+rf2IP2xfiv+wF+1J8Kv2ufghaeFL/4n/CC78T3Xhmw8c6fq2q+Er0eL/BHiXwBrVrrmnaHrnhvVLy0m8P+K9VRYrXW7E/aDC8rywrJBKAeFfEz4k+OvjJ8RPHPxZ+J3ibU/GfxF+JXizX/ABz448WazMJ9U8ReKvE+p3Osa5q99Iqonn32o3dxO0cUccEIcRW8UUKRxqAZHhPwj4r8e+JdE8GeBvDHiHxp4w8Tajb6P4c8KeE9F1LxH4l8QateOI7TS9E0LR7a81TVdRupCI7eysLW4uZ3IWKJmOKAP6n/ANjP/g0B/wCCkv7Reh+H/G3x88RfDH9jbwdrkMN2dD+IT6r47+Ndrp9zh4Lqf4X+Elt9D0yd7f8AezaJ4t+JPhXxHYSslpqej2V0LiO2AP238G/8GQv7L1jHEPiD+3J8e/E8oQCd/Bvw3+HngWOSTHzNFHrd78RWhQtkhHlnZR8pkY/NQBl+P/8AgyB/Z51DTrlPhb+3h8Z/CerHJtLnx/8ACTwR8QtOTAOEubLw74j+GNzJuOAZYr+LYMt5Mh+UgH9XP/BOD9kFv2B/2If2d/2QZPFln47ufgf4Mu/Dd/4y0/R5vD9l4m1PUvEuu+J9U1i30S4v9Um0xL3Uddupvskuo3rxMxBuZvvkA/Eb/g8E/wCUPWqf9nL/AAP/APQfGFAH+U5QAUAFAH6U/wDBMf8A4JV/tU/8FWfjbN8I/wBnPQbDT9B8M21rq3xU+MfjP+0rH4ZfCvQrt5ks5vEOq6fYahdX3iHXZLa5tvCfg/R7W71zxBc215dCKx8P6R4g1/RgD/Q5/Yz/AODSD/gl3+zxoHh2+/aA0Lxj+2T8VLGGG51rxD8RvEWveCfhs+srgyP4e+FHgLXNMtk0UAbE0jx54k+IfmlpZbi5fdBDbAH7J+Gf+CTn/BLvwfAYPD3/AATq/Yist0TQPcTfsu/BbUtQlhdSjxT6nqvgy91GeN1JDpNdOr5O4HJyAfP/AMdf+CBP/BH39oHw7qXh/wAUfsF/AbwQ9+Gkh8QfA3wrD8BPEml3m1hFe2Go/CJvCEbtA7eaLDUrXUdGunVV1DTLyHMRAP4kv+C0H/Bqn8T/ANiXwf4z/af/AGHvE3if4/fs0+DdKufEnxE+Hfi77BdfHb4SaBZJ5ureJIJ9B0rSdH+KHgTRoVm1DWdR0rR9C8VeFNHU3ep6Fr+j6Xrvi20AP496ACgD174BfHT4m/syfGr4X/tBfBrxHceE/ij8IPGmh+O/BWuwbnW11nQrxLqO3v7YOialouqQrNpWvaPclrLWtEvdQ0m/jlsr2eJwD/bZ/YB/a98Jft6/sa/s9ftc+DLWHTNM+Nfw803xHqmgQ3Yv08KeNLCe68O/ELwb9u2xtef8Ih470bxH4bF48UD3i6Wt20EBn8pQD7BoAKAP8G/9pD/k4j49f9lo+KX/AKnGu0AeL0AFAEkUUs8scMEck000iRQxRI0ksssjBI4440Bd5HchURQWZiAASaAP7XP+CUf/AAaDfFL4/wDhrwh8d/8Agov428R/s/8Aw38TaXZ+INB/Z78CRWsHx81fTL+FbrTpfiHrfiLStR0D4SrcQPb3MvhgaJ4s8Z/ZribTtch8Ba5bSRIAf17/AAK/4N5/+COPwA0WDSfDv7C/wi8f3SiJr3xB8dbXU/jrrep3MS7TdT/8LR1DxNo+nmXrLZeH9I0bSi3zLp6HOQD6wuf+CWP/AATHvNKTQ7n/AIJ1fsLy6REGEOnH9kv4Cra25YAF7aJPAKi3l4B86Dy5QQGD7gDQB+Vv7Zv/AAav/wDBJ/8Aal8Oa9J8N/hJc/shfFS/jkm0f4ifAPUdTsfDtjfqHa2i1b4N61qd58M73QfObdf6f4a0fwXrd1APItPE+mERyxgH+bZ/wVA/4JeftIf8EqP2ibz4F/HvT7bVtD1uG/174P8Axe8P286eCPjB4ItbtLb+3tD895p9I1zS5J7Wz8Y+DdRmk1bwtqk8CtNqeh6l4f8AEOuAH5u0AFAH9p//AAZeftl6/wCAP2vPjh+xHrWpb/h9+0H8Nb34r+ENPuLhj/Z3xf8AhG9kt6NJtiRHGfFfw01bxDceIZl3Tzj4feGUCGK2kdAD/SpoAKAPgX/gp1+3l4G/4JsfsUfGr9rXxrb22sXfgXQ49M+HXg24ufsz/ED4r+J5ho3w+8HIyOt0LK+1y4iv/El1ZLNd6R4P0zxFr0dvOulPGwB/iqfG/wCNPxL/AGjfi98R/jt8ZPFOoeNfij8V/F+teN/G/ibU5C9xqeu65dyXdz5MWTFY6bZq8en6PpNosWnaNpFrY6TptvbafZW1vGAeWUAe4fs3/s4/Gb9rf43fDz9nX9n3wRqXxD+LnxR11NA8I+F9NaCA3E4gmvdQ1HUtQvJYNP0XQNC0q1vdb8Q69qlza6Xomi2F9qmo3MFpayyKAf6dH/BLL/g1a/Yf/Y38LeFPiB+1v4W8M/tj/tOPp8F54h/4T3Tk179nvwPq86+ZcaR4D+F2s2MemeL4dNLrZ/8ACWfE/T9cvNSuLVdb0Xw74Ie4OlwAH9QPhfwp4W8D6Dp3hbwX4a0Dwh4Y0eAWuk+HPC+jadoGg6XbKSVt9O0jSba00+ygUkkQ21vFGCThaAL+raRpWv6ZfaLrumafrWj6nbS2epaTq1lbajpmo2c6lJrS+sLyOa1u7aZCVlguIpIpFJDqQaAP5x/+CnP/AAbG/wDBPr9uzwr4j8UfBr4f+GP2Pf2lV0y9m8MfEH4NeHdP8L/DbxHrqpJNZ2vxV+E2h2tp4X1fTr67eT+1PE3hWw8OePBNcLqN3rWvwWS6HeAH+XN+19+yL8d/2F/2hPiD+zJ+0f4Qfwb8UvhzqENtqVtDcDUND13SdQt47/QPFvhPWo0jg13wp4m0qe31PRtTiSGUwzPZ6laadrFnqOm2YB80UAes/An44/FD9mn4x/Df4+fBbxZqPgj4p/CfxZpXjPwV4n0yRkn0/WNJnEixXMWRFqGk6lbtcaVruj3iy6drmiX2oaPqdvc6ffXVvKAf7c37Bv7XXgb9vH9j/wCAP7Wnw+MEOh/Gj4faV4j1DR4LgXTeE/GVq02i/EDwRczgky3ngrxxpniDwvczHi5l0o3Ue6GaN2APrmgD5G/bq/Yv+D3/AAUE/ZZ+LH7KXxw037T4N+JugSWllrltbwTa74D8YWDfbfB/xC8LST4W38ReENditNVs1Z1tdSgiu9D1VLnRdV1OyuQD/Fl/bT/ZB+MX7B/7TfxZ/ZW+Omj/ANl+P/hT4kn0mW9t45xovi3w/col/wCFfHfhe4nSOS88L+M/D9zp/iDRZ5ES5itb4WWowWeqWl9ZWwB8tUAdJ4O8YeKfh74u8L+PfA+v6r4V8aeCfEWi+LfCPifQ7yXT9a8OeJvDuo22r6FrukX8DLPZ6npOqWdrf2N1EyyQXMEUqEMoNAH+yZ/wRB/4Kl+Fv+CrH7EvhH4v3Nzpen/H34efYfhx+0x4KsPJtv7F+Jen6ekieLdL0xSJLXwb8TNOjHizwwVR7Ownl13wjFe31/4R1SagD9iKAPIfj98dvhf+zF8Ffid+0F8afE1r4P8AhZ8IvB2s+OPGviC7w32TR9Gtmma3sbbcsupa1qtybfSdA0a133+ua5fafpGnRT319bwuAf4tX/BT/wD4KD/FD/gpv+2R8Uf2qfiS11ptj4hvR4d+FfgSW7N3ZfDD4Q6Bc3aeCPA1iyn7O9zaWtzcaz4nv7WO3g1zxprXiTxAttbf2r9niAPz6oAu6bpuo6zqNhpGkWF7qurare2um6Xpem2s99qOpajfTpa2VhYWVqktzeXt5cyxW9ra28Uk9xPIkUSPI6qQD/Xg/wCDd7/gkFp3/BLb9kG11j4laJZH9r79omy0Txn8edUdILm88DaclvJdeD/ghpl7HvRLLwNbX89x4sls5ZYNZ8fajrkq32p6JpXhdrMA/av47/AD4LftPfDPXPgz+0F8NPCfxd+FfiW40e71/wAB+NtMj1fw5q1z4f1ey17RZ72wlISaTTNZ06x1K0Yn91dWsMo5WgD4B/4cXf8ABH7/AKR2/sv/APhu7H/45QB/JR/wdu/8E9v2JP2Nf2Zv2T/Ff7LH7Mfwk+BHiPxj8dvFXh/xRrPw68MW+g32u6JafD+71K20zUZoXYz2kF+i3UcTcLMocc0AfweUAFAH90P/AAaM/wDBP/8AYr/bN+CP7Zev/tU/s0/Cf48az4H+Knwv0jwjqXxG8NQa9deHtM1bwj4jvdSsdMkmdTb297d21vPcIv8ArJIUY/doA/r5/wCHF3/BH7/pHb+y/wD+G7sf/jlAB/w4u/4I/f8ASO39l/8A8N3Y/wDxygA/4cXf8Efv+kdv7L//AIbux/8AjlAH3v8AAP8AZ2+B37LXw3074P8A7O3wu8IfB74YaRqGrarpngfwNpcej+HrHUddvZNR1i8t7GIsiT6jfSyXV04OZJnZzyaAPZ6ACgAoAKACgAoAKACgAoA/zB/+D1T/AJSm/ALp/wAmBfCzr/2cV+1T+JPPHp+JyAfyCcZ/hx9e2T/npzk80ALxnt+fbH+c+q9aAEHTtk54z9ehz/X1oAPb5e3fngfr/h160ABx/s9RyTx0P6/n6/QAXjdnjp1zz1+v05+nNACHHbb09cdwfUe5/wD18gDuO+PxOf5/Tn396AEGOvHQZ54zyfX6YoATjPbHse3ze/5/U0AL37dR35+6ff8A/WM/WgBBjAzjv3z3+p4/r70AHY9O3U5HQe5/D8KADuOB3yc/r7+/Hr26gCnoemfcn1HU5z/kUAJxn+HGW7/T3/P2+poA/tH/AODJr/k+r9rL/s0mL/1dHgGgD/SsoAKAGt0/4En/AKGtAH+C58av+Sw/Fb/spHjzr0/5G/WutAHmWBntnJ789/fP1H14oATtjjnHQ+/bn8RjuDQAvr/wI8n3+vT+9njNACcfN07Dk9Tg9ef8KAF646fn/wCg8/nQAccdOMZ56cH3/wAe596AE/7559Pw/L69c7aAA9+nOc889Aex9fvf5NAA3I7dO5xnnjoenXqetACnv05z36/L9fz9qAD8s89+fvfX6/8AAsUAHvx1/HtnPPXr+OKADuDx/F39T256mgBO5Py/UH6nnnr6+2aAFBA7r7c+/wD9YfjmgBD347evHf3xj8O5z1NAH+vt/wAGuf8Aygp/Ya+v7TX/AK2H+0F/n19eaAP39oAKAPx0/wCC9f7b91+wJ/wS6/aU+MfhrW5NC+KfjDQIfgd8Fb21nNtqlr8Tfi2Lnw7Z67os+QI9Y8C+Fv8AhK/iRYltymTwaVMcu7y3AP8AGTJJJJJJJJJJySTySSeSSepoASgD96/+Dc//AIJp6Z/wUm/4KJ+DfD/xJ8PRa/8As5/s/wCmj43fHjT7+Nm0rxPpei39vZeCPhreYKrcRePvGk+nW+taczo994G0jxoYZEmgQ0Af7A1ra21jbW9lZW8FnZ2cENraWlrDHb21rbW8axQW9vBEqRQwQRIscMMarHHGqoihQBQBPQAUAFAHhP7Tn7OXws/a5+AHxZ/Zr+Nfh628TfDL4xeDNW8G+J9OuIo5JreO/iEmm67pMsiubDxH4Y1iHT/EnhnVodt1o/iHStN1S0kjurSKRQD/AA8v2nv2fvG/7KX7RXxt/Zr+I8ca+N/gb8TvGPwy8QzwIyWepXfhPW7zSo9b03ezs+ka/a29vrekTF28/TNQtJgzCQEgHhVAH6e/8EZP2qdW/Y1/4Kefsa/G201yfQfDsPxq8I+APiXOs2y0uPhR8VNSh+HnxETUoHP2e8trDw14jvddtobkbIdW0jTdQgkt72ytbqAA/wBrugAoA/xbv+C7n/KYb/gof/2cv44/9CtKAPyYoAKAPVfgd8Evij+0j8Xvh38CPgr4Q1Tx78Vfir4p0zwd4I8J6PGHu9V1rVZvLj82aRkttP02xgWfUta1nUJrbS9D0azv9Y1a7tNNsbu6iAP9c3/gi5/wQt/Z1/4JL/DOz14WulfFb9r7xn4ftrf4s/H3UdPR5NM+1xQz6j8PPhFb3kX2jwj8O7K7HlXN0gh8R+PLm2h1jxXOlrBoPhrwyAfutQAUAFABQB/LV/weCf8AKHrVP+zl/gf/AOg+MKAP8pygAoA63wB4G8UfE/x34K+GngjSp9d8afEPxb4c8DeENEthm51jxR4t1mz0DQNKtwes+oatqFpaRDvJMtAH+2F/wS6/4J9fDf8A4JmfsY/CX9lnwDFpt/rPh3SU134teO7OzW2uvib8YNfhguvHXjS8keNL2Wzm1FRo/hS11B5rrRPBWkeHNAaaUaYJHAP0JoAKACgBkscc0ckM0aSxSo8csUqrJHLHIpV45EcFXR1JV1YFWUkEEE0Af5MP/Bzx/wAErtH/AOCdv7cMXxH+DfhK28MfsuftZ2mr/ED4caNo1r9n8PfD34iaRNZRfFj4Y6dbxgQabpVpqWqaX418KadDHa6dp/h3xjD4Z0WA2vhO48oA/mooAKAP9FP/AIMpP2y7rxR8If2of2EPE1/LcXXwq8RaZ+0J8K453aVo/B3j9rbwn8SdFtgSFtNN0DxjpXhTXoIQGNxqfxE1qcsu3DAH90tABQB/g3/tIf8AJxHx6/7LR8Uv/U412gDxegAoA/tW/wCDQb/glNoX7QXxf8Yf8FGPjf4X0zxD8Mv2dPEh8CfAXw/rtlb6hp+vftAjTNL13VvHc+n3sc1vNB8IvDetaNc+HJpraRP+E68VaXr2lXdrrHgFqAP9KKgAoAKACgD8Bv8Ag5S/YQ0D9tv/AIJafHTU7Tw9Z6h8Yv2XNA1X9pD4Q64Yl/tbT1+H9kdX+Kfhy0nQpc3Np4y+F1j4lsRoiym21HxRY+EdQltrm90TThGAf5AFABQB+sf/AAQp+Ler/BX/AILA/wDBPLxfos/kXOtftNeAPhNdN5jRq+jfHi7l+COvRORncsmjfEK+AVvlL7dxX7wAP9pWgAoA/wA3j/g9G/bgu/Hv7SXwI/YJ8Ka3K3hL4CeEY/jP8VtMtbgi0vPi58T7SW18Fafq9sSd2oeCvhfF/bOkzqEAsvi7qCMZWIEIB/EdQAUAf6cP/BoX/wAEydD+AP7JN/8At/fEnwtZt8b/ANqz7fYfC7UdRtlk1XwT+znompfYrJNOMoL6bc/FXxVpV74p1SWHP9p+EtI+HssckaPeRSgH9i9ABQAUAFAH8gP/AAeAf8E8dC+Pv7EOkftw+DPDVkfjN+yHq2k23jHW7S3VNY8R/s8eNdZXRNc0W8eLZNqaeBfHOt6B4z0j7U00Xh/RLz4iXFrHEdYvXYA/zBaACgD/AEOv+DJT9qnVtd+HX7Y37GXiLXJ7my8Aa94H+P3wv0e5m882eneN49S8F/FSOwEhMtpplprHh74c3/2OEmz/ALU8S6pfLFBd313LeAH931ABQB/LR/wc+/8ABHIf8FBf2ZP+GnfgZ4WF/wDte/st+GtU1HT9P0mz83WfjP8ABS0e61vxX8MhHbobrVPE/hmWTUPGfwztkF1cXGpy+JvCWn2ct943gubEA/ynyCCQQQQcEHqD3B96AEoA/Yf/AIIhf8FSvFP/AASn/bb8IfGC4udV1H4CfEL7D8OP2l/BVh5tz/bfw01DUI3TxZpemKTHdeMvhnqLjxb4XZUjvL+GHXPCMd7Y2Hi7VJiAf7Jvg3xh4W+IfhHwt4+8Da/pfivwV438O6L4u8I+KNDvItQ0XxH4Z8R6bbaxoWu6RfQM0N5puraXeWt/Y3UTNHPbTxSoSrCgD/OP/wCDuP8A4K+/8Lw+K6/8EzfgL4o8/wCEvwM8RW+s/tMa5o15m08d/HDSyzaX8NXuLZzHe+Hvg8JGn8Q2kkslvc/FC5ls76xt9T+G2n3c4B/E3QAUAf2+f8Gkn/BHD/hcfxCt/wDgp9+0P4V874W/CTxBd6Z+yr4b1qz3Wnjr4vaJO9rrPxca2uk8q88OfCe7WXTPCNykc0N38UFutStruy1H4bNDfAH+j5QAUAFAH8SP/B7r/wAmjfsVf9nHeMv/AFWV7QB/m60AFAH+jF/wY/8A/JvX7en/AGWb4Pf+oR4qoA/uWoAKACgAoAKACgAoAKACgAoAKACgAoA/zB/+D1T/AJSm/AL2/YB+Fh/82K/ap9jmgD+QTAzk9c+/qTnpz6jtjPoTQAuee/Xvn0/zx2+8eKAE7Y+vfjHfJxz169uvO00AA6jHtnk56Y5GB/nnpmgAPJz+PJIz77v6fj35AF7556e/rnpj+vNACNg++M9+/Hsfp9eOpoAcD/nBH8/8/wBQBB/T3J4z/nP8XagBO+e49fx4/HPGM/jj5gA753L2/QY6Z9+n457UAA47r+fv6/8A1vzzkABxjqp/H6d/w9OevfgAOMg5XjPf2x7k5/T3oACcjG5fz/z/AJHvwAHGc5HUnr6/z/THvQB/aN/wZNMv/Ddf7WQ3KSf2SIjgMCf+S0eAM+/G5c/7y+ooA/0raACgBrdP+BJ/6GtAH+C38aiG+L/xUKuhDfEjx5yCDwfF2snrnupBHqCD3zQB5l3+8vr178/zz/Lk45AEH+8ufr75659evr+tAB6/MvII/M59f/1e/WgAPf5hz79eCPw4PvmgA9PmXjPf2x68+2eaAD/gQ7d+nGPx/TPXtggCHOR9c9Dx0/PHT1/E0AHX/wAez27YyfT8enXocUAHU89xk8YHJz159OvOelACnJOee+eMdRjnrjp36de+KADnP69Cf4sn/wCv+XXmgBP/AK/bP8Q7duAOPQD1oAXr9f8AE5bA/ix3Hboc9aAE/mevUknDdfQ/57GgBOTjqfz9T+fXr70AO7de3PB7579up+bv+ByAf6+//Brn/wAoKf2Gv+7mf/Ww/wBoL/OO1AH7+0AFAH8BP/B73+0PeJB+wz+ydpt4VsLib4mftD+M9P8ANJE15Zppvw2+Gl55IICm2hvvizB5sgYv9r2QlNk/mAH+f7QAUAf6Z/8AwZZ/s7aX4F/YJ/aC/aRuLPy/Fn7QH7Qsng+O8aIDz/h98EPCum2/h1Ypm+c48afED4kpcImIz5FsSWkQiMA/spoAKACgAoAKAP8AJb/4OzPhHpXwv/4LNfF/X9Jg+yxfG34U/BT4u3lukax266rJ4PX4a6ncW6rwf7RvPhrLql5Ifmm1O9vpWyzkkA/mroAcjvG6yRuySIyujoxV0dSGV1ZSGVlYAqwIIIBBzQB/urfsQ/FnVvj3+xf+yL8c9enW5174zfsxfAT4q65cKSwm1n4hfCvwp4t1WTJ5y1/q9wWDfMGyGAYEUAfUFAH+Ld/wXc/5TDf8FD/+zl/HH/oVpQB+TFABQB/oa/8ABmN/wTp0/RvAvxc/4KX/ABE0O0udf8ZX+rfAf9nR762hnn0bwpoVxBJ8X/HemtKsy29z4m8RJp/w+03ULZrTU7Gy8JeO9NkMml+JnWYA/vDoAKACgAoAKAP5av8Ag8E/5Q9ap/2cv8D/AP0HxhQB/lOUAFAH9C//AAa4/s96T+0B/wAFlv2cZvEWlrq/h74F6N8Qv2hL+0kQNFFq3w/8NTWHgHVJCVby20P4n+JfBGt2zjB+2afbJuG+gD/XhoAKACgAoAKAP5p/+Dr/APZZsf2h/wDgkT8TfH9vaxyeMf2U/HXgT49+G51j/wBKl0hdU/4Vx4+0z7Qqs8dgfB3jzUvEt1Af3Nze+FNLaTD28MkYB/kv0AFAH9Ln/Bpd8cP+FRf8FlfhV4Unu/senftDfCT40fBS/kd9lu8ieFl+MGi282TgveeI/hHo9haDBZ728t4lx5hNAH+s5QAUAf4N/wC0h/ycR8ev+y0fFL/1ONdoA8XoAKAP9oz/AIIU/sxaV+yX/wAEm/2JfhlZ2q2+teIvgv4b+NHjmVofKvZ/HXx2g/4W14httRbG6e58Oy+LYPCEEr5I03w7YQJ+6hjAAP1soAKACgAoA53xf4W0bxz4S8UeCfEdqL3w94x8O634W16ybGLvRvEOm3Ok6pancrLi4sbueI7lYYflSOCAf4IXiLR5/DviDXfD9ySbnQtZ1PR7gldpM+mXs9lKSuTtJkgYlcnB4yaAMagD60/YG16bwr+3X+xZ4nt932jw5+1p+zlr0Gw4fztH+MPg7UItp7Nvt12nPBoA/wB0SgAoA/xDP+Crn7Q95+1Z/wAFJf21/jzc3hv7Hxt+0P8AEW18LXBlM5/4V/4M1mXwF8NrfzSSJPsfw/8AC/hqz3JtiPkfukSLYigH59UAdP4J8Jat4+8Z+EfAugRefrvjXxPoHhLRYMM3nat4j1W00fTotq5ZvMvLyFMKCxzgc0Af7v3wN+EXhX9n/wCCvwi+BPgWD7N4L+DPwz8C/CvwnCY0iZPDvgDwxpnhXRzKkeVEz2GlQPOQWLzM7szMxYgHqdABQAUAFAHyt+3P8I9K+Pv7Fv7WfwU1qD7Rp/xT/Zx+NHgZwI1klgufEXw88Q6dp9/aq3AvtN1Ge11Gwk4aK9tbeVSGQGgD/CwoAKAP6X/+DSf4uax8OP8AgtB8IfBunXPkad8fPhF8evhT4iiZ2VLrTNG+HWp/G6zjK52NIuv/AAe0Z4y/PDqh3PggH+szQAUAFAH+XR/wdSf8Ecf+GLP2hW/bc+AfhX7H+y7+0/4rvZfGei6NZ+VpHwZ+P+qLd6xrWjJbwIIdM8HfFFINS8XeEY4yLPS9ft/GHhmCDStKtPClneAH8j1ABQB/VX/wTg/4OXfi1+wz/wAEuPj7+xld2et+KfjX4Zsv7J/YZ+ItwsOo6f8ADXSfiDeXsPjew8VyX0rM9l8J5bi78dfCi0e01iDUNa1c+EdVisvCej6bbxgH8seqapqeuanqOta1qN9q+s6xf3mqatq2qXdxf6nqmp6hcSXd/qOo311JLdXt9e3U0tzd3dzLJcXNxLJNNI8jsxAKFAH6jf8ABIP/AIJmfEX/AIKqftm+Bf2d/C/9p6F8N9MMXjj4/wDxJs7cPD8O/hHo99ax65eW080U1o3izxNNPb+FPA2nzR3C3PiPVba+vLY6DpWuXlkAf7Nfwf8AhH8OvgJ8LPh98FfhH4V0zwR8Mvhb4S0TwP4G8KaRGY7HRPDnh6xh0/TrRGdnnup/JhE19qF5LPqGp30tzqOoXNzfXVxcSAHo9ABQAUAfxI/8Huv/ACaN+xV/2cd4y/8AVZXtAH+brQAUAf6MX/Bj/wD8m9ft6f8AZZvg9/6hHiqgD+5agAoAKACgAoAKACgAoAKACgAoAKACgD/MG/4PVf8AlKb8A+uf+GAfhbjgn/m4r9qrPRhQB/ILznoc/T3/AN73P+OMigA59D1zyOc9O7/5HNACZ46HAz2P4/x+/wDP3oAXnrg/iPw/vZ79yfbAoAQ5PGD7cfX1Yj1/D8KADJ9+noffr8/1xnn0oAD7g/kfb0f1x+PvmgBcn3/EH39X/wA8e1ACZPv07Dtz/t/XHr1oA/pJ/wCDUbRNG8Q/8FjPhFpev6RpWuadP8I/2hGl0/WdNstVspHi+Gt48TvaahDc2zPG3zIzRsRyM4ZgQD/Ve/4Uv8Iv+iX/AA6/8IXwl/8AKagA/wCFL/CL/ol/w6/8IXwl/wDKagA/4Uv8Iv8Aol/w6/8ACF8Jf/KagA/4Uv8ACL/ol/w6/wDCF8Jf/KagA/4Uv8Iv+iX/AA6/8IXwl/8AKagA/wCFL/CL/ol/w6/8IXwl/wDKagDf8PeAfA/hK6nvfC/g/wALeHby6txa3N3oPhzRdGubi2EgmFvPPpljaSzQCVVkEMjtGJFV9u8BqAOuoAKACgDzWT4NfCSV3kk+GPw8eSR3kkd/A3hR3kkkdpJJHdtHZnd3Zmd2JZmJZiWJJAGf8KX+EX/RL/h1/wCEL4S/+U1AB/wpf4Rf9Ev+HX/hC+Ev/lNQAf8ACl/hF/0S/wCHX/hC+Ev/AJTUAH/Cl/hF/wBEv+HX/hC+Ev8A5TUAH/Cl/hF/0S/4df8AhC+Ev/lNQB8zftqfCL4V2H7HX7WF5Z/Db4f213bfs0fHua3uYPBPhaGeCaP4T+L3jlhmi0hJIpEcBldGVgR1wSCAf4esn3l/3IT/AOQIj07/AOec8EAj/wADng9x3+b6fj1wTmgA9c56env/AL3+A9O+QAz169DnIPp3+Y0AL379SO/rz/Fnr36dfpQAn5/kc8kHs2c9M5OfU8gUAH4Hv2Prz/F+eOfXvkAPzz16cng+h+vX5u5PBwAHT14z0B9eejc4/wD180AL2/Dnr/tf7XT+ee3GAD/X2/4Nc/8AlBT+w1/3c17f83h/tBe5/nQB+/tABQB/lTf8HhfxEn8Z/wDBX648LvdtNB8JP2ZPgr4Eht9+Y7NtXuvGnxQmQIOFkmPxESeRiN7o8QZiiRhQD+WCgAoA/dz9iH/g4s/4KMf8E+v2cPBX7LH7Ot58DtO+FngS/wDFuqaQPFfwpj8R+JLq/wDGnivWPGGs3Wr622v2Rv5f7S1qe1sz9li+zaXbWNn8/wBm81wD6z/4jAP+CxP/AEHf2bv/AAx0P/zU0AH/ABGAf8Fif+g7+zd/4Y6H/wCamgA/4jAP+CxP/Qd/Zu/8MdD/APNTQAf8RgH/AAWJ/wCg7+zd/wCGOh/+amgA/wCIwD/gsT/0Hf2bv/DHQ/8AzU0Afi9/wUN/4KLftGf8FOvjfoP7Qf7T83ga4+Inh34aaF8KbGfwD4UXwfpMvhXw74j8XeKNNN5pq3+oi41RdR8a6xHLf+ehlsksLbyl+y75AD4RoAKAP9p3/ghl4obxf/wSA/4J26szs5tP2XPht4Xy2chfBGmt4LRef4UTQFRe21RjigD9W6AP8W7/AILuf8phv+Ch/wD2cv44/wDQrSgD8mKACgD/AGx/+CNHwO0f9nX/AIJV/sD/AAt0aEQLbfszfDPxvrSCIQg+Mfi5okXxc8dybBkkS+NPHGvyK7/vJFYPIFdmUAH6Y0AFABQAUAFAH8tX/B4J/wAoetU/7OX+B/8A6D4woA/ynKACgD+0r/gyV8L2t5+3R+1x4zktY5Lzw9+yfb+Gra8ZcyW8Hi74veA9TuoI2/hF03gy2d+7fZVGcBsgH+ldQAUAFABQAUAfF/8AwUd+Gtl8Yv8Agn3+298Lr9FaLx1+yd+0D4egkZPMNpqV98K/FK6RqMaYO6fTNWFlqNvkMPPtYyVYZBAP8NegAoA/TX/gi94ml8Jf8Fav+CcWqw3D2z3X7ZPwC8MtJG7Rs0XjT4h6H4OngLKQTHdQa9JbSoTtkimeNwyuVIB/th0AFAH+Df8AtIf8nEfHr/stHxS/9TjXaAPF6AOj8H+HZ/F/i7wt4TtpfJufFHiPRPDtvNsMnlT63qdrpsUvlgqZPLkuVfYGUvjbkZzQB/vceFvDmleDvDPh3wjoNuLTQ/CuhaR4c0a1GMW2laHp9vpmnW42hVxDZ2sMYwqj5eABxQBu0AFABQAUAFAH+DN+0GiR/Hz43xxqqRx/F/4lIiKAFRF8Z60qqoHAVQAABwAKAPIKAPpP9jP/AJPA/ZS/7OT+Bn/q0PC9AH+7LQB49+0N4/b4UfAH45fFNJxbP8Nfg98TPH6XJ24t28HeC9b8RLOdwK4iOnCQ7gV+XkEZoA/wa5JJJpJJppHllld5JZZHaSSSR2LPJI7Es7uxLO7EszEkkkk0AMoA9D+EXxN8RfBX4r/DD4yeEIdIuPFvwl+Ifgv4m+F7fX7D+1dCn8ReA/Emm+KdEh1vSzNb/wBpaRLqelWyalYGeH7ZZtNb+dH5m8AH9Jn/ABGAf8Fif+g7+zd/4Y6H/wCamgA/4jAP+CxP/Qd/Zu/8MdD/APNTQAf8RgH/AAWJ/wCg7+zd/wCGOh/+amgA/wCIwD/gsT/0Hf2bv/DHQ/8AzU0AH/EYB/wWJ/6Dv7N3/hjof/mpoAguv+Dvb/gsFe21zZ3Wsfs2TW13BNbXML/A2EpLBcRtFNE4/wCEp5WSN2Vh3BNAH8u9ABQB+0X/AAbu+KG8If8ABab9gDVldkN38XNa8LkrnJXxv8NPHXgt1OP4ZE19kbttY54zQB/srUAFABQB8+ftV/sxfCH9sz9nn4r/ALMfx28Op4m+F/xf8KXvhfxFZjyk1DT5JGju9F8TaBdzQzrpvinwlrtrpvibwvqohlbTNe0rT73ypRCY3AP8Wv8A4KL/ALB3xd/4Jt/tcfFL9lH4xW73Gp+CtSGoeC/GMNnLZ6N8TfhlrUtxP4I+Ivh8SNKn2HxBpsTR6jZRXN23h/xNY6/4WvbmTU9CvgoB8PUAFABQB0ng3wf4q+Ifi7wv4B8DeH9W8WeNfG3iHRvCXhHwvoVnNqOt+I/E3iLUbfSNC0PSLC3V573U9W1O7trGxtYUaW4uZ44kBZhQB/sY/wDBC/8A4JQeFf8AglD+xloPw61O10rU/wBpH4rjSviB+0143sfJuhf+N3sXXS/h/oupqGkufBXwtsL258P6CVl+yarrFx4o8Yw21jL4suLK3AP2joAKACgAoA/iR/4Pdf8Ak0b9ir/s47xl/wCqyvaAP83WgAoA/wBGL/gx/wD+Tev29P8Ass3we/8AUI8VUAf3LUAFABQAUAFABQAUAFABQAUAFABQAUAf5g//AAeqf8pTfgF6/wDDAPwtx9f+Giv2qf8AZNAH8gfGe3frjoCf9nHPX370AL9T/wCg9Mdfu/h9PagBOMDnse4zjn/Zz6//AF6AD8vzXOMf7vTH6UAHHrxkemM8/wCzjOOv8+lABxnqOnPI/D+HHp/9fFAAceoP4j29F6/59aAHEDue567fx/h6+tACcc89hnpj2z8uPx/+tQB/S3/waXf8pmvg9g/80i/aH/8AVZ3npQB/rMUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAfLv7b/wDyZj+1v/2bH8fv/VS+L6AP8LGT7y/7kH/omL/P/wBfFAEf/wBlnJ5zt78fn155PPFACeuc9O59x6A8enUdcUAL35z37j+77D0x6/iaAAnk9+vpk/MPbI5z+PQ96AEyeev6Zzkd8dfXv070AH/18cjrnnHy9Qf/AK3rQAuRjP59PRvYf1/LqAJnpxn/AL5/vH2P6dz78gDu3OenPPb5vbp6de34gH+vt/wa5/8AKCn9hv6/tNf+th/tBfSgD9/aACgD/IT/AODpjUHvf+C537aEDFiulWP7Nmnx5yPlb9lL4Iai2AecedqEvPQnLDIIJAP586ACgAoAKACgAoAKACgAoAKACgD/AGaP+DfP/lDH/wAE+/8AsiJ/9TTxZQB+yFAH+Ld/wXc/5TDf8FD/APs5fxx/6FaUAfkxQAUAf7x37NmmWmi/s6fALRrBPKsdJ+Cvws0yzj/552lh4G0K1t04AHyQxIvAHTpQB7VQAUAFABQAUAfy1f8AB4J/yh61T/s5f4H/APoPjCgD/KcoAKAP7mv+DH4W/wDw0B+3wzBPtY+DvwZEJP8ArPs7eNfGBugv+wZVtN/+0I6AP9F6gAoAKACgAoA81+M2n22rfB/4r6VeOkdpqfw18dafdSSf6tLa98L6pbTu/X5FilZm4PANAH+CjQAUAfZH/BOrVbrQv+Cgv7CmuWSSSXmjftkfsxaraRxcyyXWnfGzwReQJH/00eWFFT/aIoA/3MKACgD/AAb/ANpD/k4j49f9lo+KX/qca7QB4vQB9E/sg6QniD9rP9l7QZACmt/tE/BPSHDfdKal8SvDNmwbPGCJjnPagD/dvoAKACgAoAKACgD/AAaP2h/+S/8Axy/7LD8TP/U11ugDx6gD6T/Yz/5PA/ZS/wCzk/gZ/wCrQ8L0Af7stAHwd/wVO1B9J/4Ji/8ABRnVIywk079hH9ru9jK5Lebbfs//ABBmjxjODvReeg6sQATQB/h8UAFABQAUAFABQAUAFABQAUAFAH62/wDBBz/lMT/wTy/7OR8H/wDonUKAP9ougAoAKACgD+QH/g8Z+AH7J/iv9gXwd+0J8UvEdh4I/ac+F/xB0bwh+zldWNlDd+I/iva+Mb+CTx98KNSgSWG4m8KaX4dtL/4krrtyZIfCOr+GktLJ45fG17p2uAH+YLQAUAFAH9j3/Bmt8Av2Tvid+2v8Xfip8WPEdhqn7S3wL8A2HiD9m/4Va3ZQjT3sfEE1/oHxF+MOkXE0rpq/inwHa3Wi+G7DTDAh0G18dXPieBLy/trG/wDDgB/ptUAFABQAUAFAH8SP/B7r/wAmjfsVf9nHeMv/AFWV7QB/m60AFAH+jF/wY/8A/JvX7en/AGWb4Pf+oR4qoA/uWoAKACgAoAKACgAoAKACgAoAKACgAoA/zBv+D1U/8bTfgF15/YB+FnT/ALOK/ap9++fUfU0AfyC857//AK2+vt16YP4EAUZ756jr+fqep469e+OKAEySM898/hzz+Xp3577gABPHX6889+ee/wBT17cggASQf6fUk+/Xp0z9KADnOOehP55/2v6n8OtAAxI9e/T8B6+/+fvUAKPrnn1Pv/tHrnP9PQAOvftnrzzn3HI7/pigD+lv/g0v/wCUzfwe/wCyRftD/wDqs7ygD/WXoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoA+Xf23/+TMf2t/8As2P4/f8AqpfF9AH+FhL95P8Ach/9ERc/z/WgCPJ4OTxnn14BHfv7559RwAA+737evv06npn3/rQApOD1PGfXnjPc+/Gc89cjigAOc8k+mef72PX2yeenqeaAE/4Efrn1Iweo6j69D3HAAp+pHXnPTBx6/wBfxY0AHPqeOc5PcHnt9OpHPXrkAbyOpI659snvz36/49aAHZwOvT69eeP078dOOuQD/X3/AODXPn/ghT+w1/3cz/62H+0F/n+p60Afv7QAUAf5Gn/B1n4dudE/4LfftSanPAYovF/hD9nPxFZSEcXNtbfs9fDXwk86+oW88L3dtnn5rdh2oA/nSoAKAP7tv+CSn/Brf+wt/wAFDf8Agnl+zd+2J46/aA/ao8LeMvjHovjefxP4e8D618I4fCmla14J+KXjn4b39vosOvfCjXNXitTN4PaZkv8AVr6ZZpZf33l7FUA/Rn/iCd/4J1/9HP8A7af/AIP/AIG//OToAP8AiCd/4J1/9HP/ALaf/g/+Bv8A85OgA/4gnf8AgnX/ANHP/tp/+D/4G/8Azk6AD/iCd/4J1/8ARz/7af8A4P8A4G//ADk6AD/iCd/4J1/9HP8A7af/AIP/AIG//OToAP8AiCd/4J1/9HP/ALaf/g/+Bv8A85OgA/4gnf8AgnX/ANHP/tp/+D/4G/8Azk6AD/iCd/4J1/8ARz/7af8A4P8A4G//ADk6AP6i/wBi/wDZV8E/sQ/sufBj9lD4ca/4q8U+B/gj4T/4RDw54g8bTaTceK9UsP7U1HVvtOtzaFpWh6RJd+fqc0ebHSbGHykjHlbw7uAfT1AH+Ld/wXc/5TDf8FD/APs5fxx/6FaUAfkxQAUAf7z3wC/5IT8Ff+yS/Dj/ANQ7RqAPWqACgAoAKACgD+Wr/g8E/wCUPWqf9nL/AAP/APQfGFAH+U5QAUAf2uf8GR+trB+2j+2P4cMqh9V/Zf0LW1hLANIvh/4reGrB5QmcssJ8TIrMAQpnUEguMgH+k5QAUAFABQAUAfP37WniSDwb+yt+0x4vurmOztfCv7P3xm8SXN3K4jitYND+HPiTVJrmSQkBI4I7VpXckBVUsTxQB/hEUAFAH3//AMEoPD3/AAlX/BUL/gnRoLR+bDf/ALcX7K32xMbt2n2vxv8ABF7qXHfFhb3J544yeM0Af7fNABQB/g3/ALSH/JxHx6/7LR8Uv/U412gDxegD6l/Ya/5PY/Y9/wCzpf2ff/Vs+EqAP91OgAoAKACgAoAKAP8ABo/aH/5L/wDHL/ssPxM/9TXW6APHqAPpP9jP/k8D9lL/ALOT+Bn/AKtDwvQB/uy0AfF//BSDw7c+L/8Agnh+3p4SsoDc3nij9i/9qPw7aWyjLXFzrfwP8c6bBAo5yZZblIwO5agD/DXoAKAPrT9gv4GeAv2nv21/2Uv2bvifrniTwz4D+Pnx++Fnwb8Ra/4Pn0u28T6TbfErxhpXg+3vdEn1vTNa0mPUIr/WLUwnUNKvrYkkPA+RgA/0G/8AiCd/4J1/9HP/ALaf/g/+Bv8A85OgA/4gnf8AgnX/ANHP/tp/+D/4G/8Azk6AD/iCd/4J1/8ARz/7af8A4P8A4G//ADk6AD/iCd/4J1/9HP8A7af/AIP/AIG//OToAP8AiCd/4J1/9HP/ALaf/g/+Bv8A85OgA/4gnf8AgnX/ANHP/tp/+D/4G/8Azk6AD/iCd/4J1/8ARz/7af8A4P8A4G//ADk6AD/iCd/4J1/9HP8A7af/AIP/AIG//OToA+kf2P8A/g04/Yd/Yy/ac+Cn7U/w+/aC/at8TeNfgb450zx94b0DxlrXwhn8L6rqmlrOsFprkOifCbRtWksJPPYyrYarY3BwNlwnOQD+pigAoAKAOa8Z+MvCvw78IeKfH/jvxDpPhLwT4I8O614t8X+KdevYdO0Tw54Z8O6dc6vruu6vf3DJBZabpWmWl1fX11M6xwW0EkjkKpoA/wAc3/gud/wVe8Vf8FX/ANs3X/iRp1zq2l/s4fCo6r8P/wBmXwPf+dbNp/gZL5G1Px9rWmMRHbeNvilf2dt4h18NGbrS9Jt/C/g6a6v4fCdtezgH4vUAFABQB9A/srftOfF79jX9oT4U/tN/AnxHJ4Y+KPwg8V2Xinw3fHzZLC/SNZLTWfDev2kU0Dan4X8WaHdaj4a8UaS00SapoGq6hYtJH5/mKAf7SH/BOL9vb4Rf8FKP2Rvhf+1b8H7hLax8YaedL8deC5byK81n4YfFDRYbaLxv8O9eZFikN3oWoTpcaVfzW1mPEPhfUfD/AIptLWLT9dswQD7noAKACgAoA/iR/wCD3X/k0b9ir/s47xl/6rK9oA/zdaACgD/Ri/4Mf/8Ak3r9vT/ss3we/wDUI8VUAf3LUAFABQAUAFABQAUAFABQAUAFABQAUAf5g/8Aweqf8pTfgFxn/jAH4W98f83FftU/r/WgD+QTjPQenUY5J/Xj69c80ALx6d8c4/u59/5/pxQAnG0cdd3/ALNxnr6/4+oADGQMDnvkHqCcfTt9MevIAEgDpnn+np/Q+o+gAF4z07Z6jPU+/wD+rj0GABGx6evt3H9T1/oc0AO69RQAg+nZT/P6c0Afoz/wSv8A+Chmtf8ABL/9sDwn+1r4f+FulfGDUvCvhL4g+FYvBGs+Kr3wbY3iePPDk3h2W+fXNP0bXrmF9NWT7UkC6dILrDQma2YrOgB/Un/xHAfF/wD6R6/Dn/xInxb/APOvoAP+I4D4v/8ASPX4c/8AiRPi3/519AB/xHAfF7/pHt8Of/EifFv/AM6+gA/4jgPi/wD9I9fhz/4kT4t/+dfQAf8AEcB8X/8ApHr8Of8AxInxb/8AOvoAP+I4D4v/APSPX4c/+JE+Lf8A519AH7g/8ELP+DhDxz/wV++P/wAYPgx4p/Zj8KfA6y+GPwcT4oW2v6D8Udb8d3Wr3L+OfDvhH+x57DU/B/h2G0h8vXZL37XHdTyh7VIPJZZ2eEA/qFoAKAEJxz7gfmQP60Af58Xjf/g9f+LnhLxn4t8Kp/wT/wDh1fJ4a8T+IdAjvG/aE8WQPdR6LrN9paXLwr8MXWJ5xaea0au6qWwGxwADl/8AiOA+L/8A0j1+HP8A4kT4t/8AnX0AH/EcB8X/APpHr8Of/EifFv8A86+gA/4jgPi//wBI9fhz/wCJE+Lf/nX0AH/EcB8X/wDpHr8Of/EifFv/AM6+gA/4jgPi/wD9I9fhz/4kT4t/+dfQB5v8ZP8Ag86+Kvxg+EPxV+Et7+wR8PtFtPij8NfHnw6uNag+P/iq+n0eLxx4U1fwvJqsNlL8NII7yTTl1VrxbR7i3W6MPkfabYuLiMA/iaZixU9OEX1+7HGoP44yR69+M0AN/wDss+vTn+fvzySaAA+/90fjkjpyePw/AZoACDnrnGc5P+zn9R9emaAF5z29ef8Ae+vTIzj37nmgA5/X9QwPr15weecdT1oATGMdzzj22nJ/PHt7nvQAeo4HY+/Dc9sd+T/+sAOTjGORnjjoT7+p/H6igBecf8BBP0+b3+vr1HAxQB/r7/8ABrn/AMoKf2G/r+01/wCth/tBUAfv7QAUAf5j3/B6b8G7vwj/AMFE/gF8Z4YGTRPjL+yzo+iPOUwJ/F3wq+IPjWy1wLIMBxD4Z8XeA1KHMkbMSzFJIlUA/jooAKAP9T7/AIM7fj/p/wAUP+CUl78HmmjTXv2Zv2gPiX4MmsPM3zt4Y+Isth8X9C1pk3HyrfUNe8aeNNKgX5S03h67cr8wdwD+rqgAoAKACgAoAKACgAoAKACgD/Fu/wCC7n/KYb/gof8A9nL+OP8A0K0oA/JigAoA/wB574Bf8kJ+Cv8A2SX4cf8AqHaNQB61QAUAFABQAUAfy1f8Hgn/ACh61T/s5f4H/wDoPjCgD/KcoAKAP6e/+DRL4uRfDX/gsf4K8JzXsdpH8ePgJ8b/AITBJZViS8n07SNJ+M9taDewV5pJvhErQJy7yIEjBdgCAf6vtABQAUAFABQB+NX/AAcGfHCx+Af/AARy/bw8UXOpx6de+M/gxf8AwS0ZDJsudS1H476rpnwkm0+xRf3k0/8AY/i/Vr6dYwTDp1jfXkhSC2mkQA/xnKACgD9u/wDg3I+Dt58av+Cz/wCw3ocEcn2LwV8Q9e+MWsXaLujsbP4PeA/FXxDsZLg4bbHfeINA0XRY2x/x9apbjcgYyKAf7HtABQB/g3/tIf8AJxHx6/7LR8Uv/U412gDxegD6l/Ya/wCT2P2Pf+zpf2ff/Vs+EqAP91OgAoAKACgAoAKAP8Gj9of/AJL/APHL/ssPxM/9TXW6APHqAPpP9jP/AJPA/ZS/7OT+Bn/q0PC9AH+7LQBz/izw3pvjLwr4m8Iayhk0jxX4f1nw3qsa7S0mm67p1zpd8i7wy5a2upVG5WXJ5BGRQB/gw/FD4f658J/iX8RPhZ4nj8nxL8NPHXi34f8AiGLY0fla54N1/UPDurR+W5Lx7L/TbhdjEsuNrEkGgDhaAPYf2efizefAT4//AAN+Omn2rX1/8F/jD8M/izY2SP5b3l58OfGuieMLa1WTcmxribR0iV967S+7cMZoA/3efC3ibRPGvhjw54x8M6hDq3hvxboOkeJvD+qW5LW+paJr2n2+q6TqEBPJhvLC7t7mInkpIpoA3qACgAoAKACgAoAKACgAoAKACgD/AD/v+Dun/gsh5j3H/BKj9nXxV8kZ0bxD+2P4r0K94eQfZdc8H/AGG8t36Rn+zvGvxNjhJzJ/wiXhOS7DReNtEIB/ARQAUAfs5+x5/wAEQP2tv20P+Cf/AO1N+358M9LkXwj8AGj/AOEB8Cy6Rd3PiX9oCPwvv1H4zv8AD8pLGzj4Y+Gmgv4PKtNR/wCEz1+PVPBfh/zfEek3logB+MdABQB/Qz/wbq/8Fgr/AP4Jdftc2/hn4oa5dj9j39o3UNE8I/HGwmkmnsvh5raTPZ+D/jjplmu9op/B897LYeNo7NGm1jwDfaq5stV1vw/4VhtgD/XU0/ULDVrCy1XSr201PTNTtLbUNO1LT7mG8sNQsLyFLmzvbK8t3kt7u0u7eSOe2uYJJIZ4ZElid0dWIBboAKACgD+JH/g91/5NG/Yq/wCzjvGX/qsr2gD/ADdaACgD/Ri/4Mf/APk3r9vT/ss3we/9QjxVQB/ctQAUAFABQAUAFABQAUAFABQAUAFABQB/mD/8Hqn/AClN+AXXn9gH4W98f83FftU/56igD+QTvjn/AL69yM/XuT+FAC9+/X19R/hz1+hzxQA0dM89+/sf1P0HT8wBe4PPPvnHB75OfX/OCAB/4FyR3Oe+eOvbP4+2KADvj5umfve59+/1/LrQAHj+8evVsdx69ucf5zQAuM/3h+Pr36n/ACaAEH49B0P19x1/r2OaADvjnv0Pu3+e/Tv3ADqe/Ufxeq59f17+vagAXnHXkHq3v/n0/HqAAHI/i+uc9gfXv9O/4UAHcDnqe+T0/pn19+c0AKeM9e3fHXHf8ufc8+gA059/4uSSenGf1/8A1k8gH9o//Bk3/wAn0/tZf9mlQ/8Aq6vANAH+lbQAUANbp/wJP/Q1oA/wWvjT/wAlf+Kn/ZSPHffH/M3a1/n9e2aAPMuc9e59fV/f+v8A9cABnA/DnJ7t6Z578nH9aADnn6N/M54z+vJ56HFABz83J4wep44J9e/6Z70AHOR6jPXnPHXr+OOPxzQAvPHXnHc8/KT6+v8AnmgBuDx04Pv/ALPr36enXr1wAHr/AMC756qD1zzxx+vNACnIz9OuSe4569+Ppj3oAU9/x6k8fLnoTznmgBOc/n69d3Xr644zk/jmgA5zyP1PqO5x0455z79gBcHjqfvcZPY465460AJjGffnB/4F3+mefx57gAM/Xr3I7n+Rz1xnPfGaADn9PXn+Lv69fpnpxQB/r7/8Guf/ACgp/Yb+v7TXX/s8P9oKgD9/aACgD+Qf/g8n/ZIuvjN/wTy+Gf7Tnh3R5NR8SfsifF+C48Q3UMJll0/4RfGyHT/BXiy4/dgzFI/iHpXwgkmODDb2S393MY44WkAB/l/0AFAH9T//AAaa/wDBRSw/Y8/4KCXX7PHxF8Q2mh/Bj9tvS9H+HNzfardxWel6D8b/AAvNqd/8F9XuLq4fZAniK41nxP8ADJYIlT7brXjrw3c3kyW2kAqAf6rNABQAUAFABQAUAFABQAUAFAH+Ld/wXc/5TDf8FD/+zl/HH/oVpQB+TFABQB/vPfAL/khPwV/7JL8OP/UO0agD1qgAoAKACgAoA/lq/wCDwT/lD1qn/Zy/wP8A/QfGFAH+U5QAUAfTn7Fv7R2t/sg/tb/s4ftP6B9qkvvgZ8ZfAHxHubG0cJNrWheHfEVjd+KPDbEvHm38T+Ghq3h68TzI/MtNTnTzYy29QD/cn+G3xF8FfF/4eeBviv8ADfxDYeLfh98SvCPh3x54H8UaXIZdO8Q+E/Fmk2mu+H9ZsnZVc2+o6XfWt1GJESVFlCSokisgAO1oAKACgAoA/gD/AOD1D9vLQby1/Z4/4Jz+Cta+2a5petRftK/HO3sp18rSP+JPrfhL4OeF9ReBmLX1/aa1448X6no135TWlkPAmteTOup2E8AB/AHQAUAf2of8GUn7Omp+Lf2z/wBp/wDafvdJlm8LfBj4A2vwv0zVJowttB4++M3jPRtVtTYyuAZ7608HfDLxZa3qQFxZ2mv25vBGb+xMoB/pUUAFAH+Df+0h/wAnEfHr/stHxS/9TjXaAPF6APqX9hr/AJPY/Y9/7Ol/Z9/9Wz4SoA/3U6ACgAoAKACgAoA/waP2h/8Akv8A8cv+yw/Ez/1NdboA8eoA+k/2M/8Ak8D9lL/s5P4Gf+rQ8L0Af7stABQB/kFf8HN/7JF1+yj/AMFev2i7qx0eTTfAn7SkulftQeBbnySlvqL/ABSW4b4lyI6DyPOi+Muk/ETfAjebFZy6fNMiC6jZwD+fygAoA/1nP+DWf/gopYftq/8ABN3wd8HvF3iG0u/jv+xfDpPwO8X6XNdxHWdW+Fmm2AT4H+ODZ72uDp03g+0Pw+uL+ZpJ73xF8PNa1C6MZ1K2EgB/S5QAUAFABQAUAFABQAUAFABQB+K//BdX/grD4X/4JQ/sZ678QdJu9K1L9pT4tLq3gD9mXwTfCG6F340NjG2r/EPWtMcs9z4L+FljfWuv62rxG01bW7rwr4PnuLFvFcV9bAH+Ol4w8X+KPiD4t8T+PPHGv6t4r8aeNfEOs+LPFvijXr2fUtb8R+JfEOo3Gr67rusahcvJcX2p6tqd3dX9/dzu8txdTyyyMXcmgDnKAPvb/gmh+wF8VP8Agpf+2J8K/wBlP4WpPYDxXqB1v4j+NxZvead8MPhNoM9rN468f6qmUhb+y7CeLT9Bsbm4tItf8Yat4c8Mpd29zrUEqgH+01+zr+z98K/2Vfgb8Lv2dPgl4ag8JfCv4P8Ag/SvBXg3Q4Skksem6ZERNqOqXaxxNqniDXb+S813xLrVwn2zXPEGpalrF88l5fTyMAf5e/8Awc+/8Egf+HfH7Vp/aO+Cvhf+zv2R/wBq3xBq+t6DZaVaeVovwi+NEwn1rxt8LdlugtNK0DXQbvxv8NbQC0gTRX8R+FdKsvsfgGS6uAD+XegAoA/0g/8Ag0o/4LJf8Lo+Hdr/AMExP2iPFXnfFf4Q+HrrUf2WfEmt3m678ffB/Q7drnVvhO9xdP5l54l+Etmj6h4Ut0lmnvfhek9hbWlpY/Dae4vgD+3WgAoAKAP4pf8Ag9w0q5m/Ys/Y51xR/oenftRa3pU5weLnWfhR4ovLUZ6DMWhXhweTjI6GgD/NhoAKAP8ARH/4MeNdtLj4O/8ABQnwyjob/SfiX+z/AK7cRhwZFtPEPhf4n6fZu0edyo03hi/VHIw7I6g5RqAP7saACgAoAKACgAoAKACgAoAKACgAoAKAP8yf/g9c8Mazbf8ABST9mvxnNZzJ4f1z9h/wj4a02/MbiC51fwl8evj5qeu2cUpAjeays/G/hyaaNGLxJqEDSKFljLAH8cfp9PVuvzY5z+pPTPOKAF/+v1Jz933IP/1ueM5IAg6fge5x/F2z/TPU84yAA7n1xzy390nnJ9enfH0zQAHpz6jqTjp9fU9zjHPvQAdz+Hds/jz9cdz6c8gB/PHqx5z7E8f1+nAA5v8AHqSO/wBR78/T2yAJ6/RehP8Aj+X9c8gCenryep/2u+cfrnrzQAuOevcdzn7p69s/5PWgBOg4PY9yB97tkg/59+QAxwT9O5x0HUf596AFPb/gXUn09c8e+TkH0oAD1x7+/qv+P+eSQBPT3DZ5P+P58+/PWgD+0f8A4Mm/+T6f2sv+zSoff/mtXgGgD/StoAKAGt0/4En/AKGtAH+C38af+Sv/ABU/7KR469f+hu1r0/T396APMv4h079+erdvx649efUAAOB26dCcfe/HP/1+e1AB69+H9fX/AOvz/OgBD/Fz6dz39f6dfT2oAUfw/j3Pp2yc4/OgAA6fh3PPDf57dx7UAIO3Tr6+6+pz/wDqHrggB6/8C5yT2HX+vXn0PFAARweeoByST3/Hj0/Hk80AKR1/Hux/h7//AF/50AHf8+5zy3p/9bGepIoAMdfqRnJz1X36469ume4oAMcjnqW7nPXt/XP60AIMZP1/2s9G9ec/560AKO2fQ9CT39ic+/XtntQAoUkhR1baMdfvbgMn0yeue1AH+wp/wbL+GdY8J/8ABDr9hHS9cs5rG9u9A+N3ieGGeN43fR/Gv7TXxp8ZeHrwLIqsYtQ0DXtMv4JANk0FzHLEWjdWIB+71ABQB5B+0D8D/AX7S/wN+Lv7PfxR09tU+Hnxp+HXi74Z+MLSLyluxofjHRLzRLy702aaKZbTWNOS8/tHRtQEbS6dqtrZ38G2e3jYAH+If+25+yP8Tf2E/wBqr42/sofFu1ePxj8HPG2o+HP7VW0ms7Dxd4bk2al4N8d6LDOzyDQvHHhS90fxTpCyO00NlqsVtdbLyC4ijAPlagCSKaW3linglkhnhkSaGaJ2jliljYPHLFIhDxyRuA6OrBlYBlIIzQB/pdf8G/n/AAcwfDL9ozwX8Pv2NP2/PHWnfDn9pfwvo9h4T+H3x68ca3aaf4H/AGhrPTIls9HsvF3iTVJLa28K/GZ7GO2s7iTW7s6V8TNSge/0/VbfxfrEXhm9AP7OVZWUMrBlYBlZSCrKRkMCMggg5BBwRzQAtABQAUAFAHwv+2F/wUv/AGEf2CdFn1b9q79pv4Y/Cm/S2N3Z+CLrWW8RfFHWotm9H0H4V+E4dd+IWsQOWjja+svDkunWzzwG9vLaOVZCAfHf/BLD/gt/+z//AMFcPix+0z4J/Zy+GfxM8NeBf2c9G+Guoj4g/E1tC0bUvH1z8QtR8c6fjSvBGjXmvS6HpGnDwU11aX+r+Iv7V1KLVI0vPDuiT2skcoB+1lABQB/i3f8ABdz/AJTDf8FD/wDs5fxx/wChWlAH5MUAFAH+898Av+SE/BX/ALJL8OP/AFDtGoA9aoAKACgAoAKAP5av+DwT/lD1qn/Zy/wP/wDQfGFAH+U5QAUAFAH9z/8AwbGf8HCHgH9n3wp4c/4Jy/tyeM9K8EfCfTbvVG/Zs/aA8U6j9i8PeA5db1S61nUPhN8UNZvZTaaN4OudW1C/1HwN40v5bbTPCtxdXXhnX7m38OSaFdeHwD/RM03UtO1nTrDWNHv7LVdJ1WytdS0vVNNuoL7TtS0++gS5sr+wvbWSW2vLK8tpY7i1ureWSC4gkSWKR43ViAXaACgD8j/+Ctv/AAWF/Zm/4JP/AAN1vxf8RvEmh+K/j/4g8O383wL/AGdLDVVPjT4ja+xkstN1PV7WzFxd+E/hrp2oh5/E3jjVYbaxW0sL/SvD51rxXLpuhXoB/j1/tM/tH/Fz9rz49/FP9pX47eJX8W/Fj4weKrzxb4v1nyRa2n2maOGz07SNIsFZ49L8PeHNGs9O8O+G9Iid4dI0DS9N02FmitUJAPC6ACgD/X8/4Nov2IJf2J/+CUnwSh8TaJJovxV/aSlvP2mviZDe2rW2qWsnxHstNj+Heh3kdwiX1m+jfCjSPBAv9HuxG2l+JL3xGpt4Li4ut4B+/lABQB/g3/tIf8nEfHr/ALLR8Uv/AFONdoA8XoA+pf2Gv+T2P2Pf+zpf2ff/AFbPhKgD/dToAKACgAoAKACgD/Bo/aH/AOS//HL/ALLD8TP/AFNdboA8eoA+k/2M/wDk8D9lL/s5P4Gf+rQ8L0Af7stABQB/KX/wdm/8E2NQ/bE/YW0/9p/4Z6LLqnxp/YibxH44u9P0+1M+peK/gL4hh07/AIW1paJCglubrwUNE0X4lWLXEskdloXh7xva2FtJqGvoGAP8rugAoA+8v+Cbn/BQr43/APBMj9qvwL+1H8D7lL290LzdB8f/AA/1G+ubLwz8WPhrq89s3if4f+JntknaK21FbW11HRtWFpezeGvFGmaH4ltbO6udJjtpgD/Xa/4Jo/8ABV39kb/gqZ8HbD4k/s8+N7O08a2FhA3xN+BHijUdNtPi38K9XAhjurfX/D0Vy02qeGpbmZU0Dx5osd14X1+JhFFeWmtWuraJpYB+llABQAUAFAFW9vrLTbO61HUby10/T7G3mu72+vbiK1s7O1t0aWe5urmd44be3hjVpJppnSONFZ3YKCaAPwQ/bk/4OWf+CVH7Ef8AbHh6T42j9pb4raZ59v8A8Kx/Zjj034kyW+oRbojba/8AEYanp3wp0A2l4Bb6xYSeNLzxRpm2cjwzdzwG2cA/Wn9jz9oi0/a4/ZW/Z5/agsPCtx4Gsfj/APCDwJ8W7Pwdd6vHr934ZtfHXh+y8QW+i3OtQ6fpUOqXGnxXyW817FptlHPIjOlvGpAoA+kKAPNfjJ8X/hx+z/8ACn4hfG34v+KtN8EfDD4WeEtb8ceOfFWrSFLLRvDvh+xlv9QuSiK9xd3TxxfZ9P02zin1DVdQmtdN062ur+7t7eUA/wAZH/grv/wUx+I//BVL9szx3+0Z4s/tLQ/h5YtJ4J+Afw2u7kSQ/Dj4RaPfXUmg6dPFDLLaP4q8QzXFz4q8c6jDJMt54m1a8tbKddC03RLKyAPy/oAlggmuZoba2hluLi4ljggggjeWaeaVwkUMMSBnklkdlSONFZ3dgqgkgUAf64P/AAbdf8EiIf8AgmZ+x3beOviv4ditP2vf2nNP0Lxp8YmvrdDq3w18JrA954F+CUErrvs5vDdrfSa349jhCG78e6rqGmXFxqmm+E/Dd1EAf0ZUAfH37en7FXwi/wCChP7Kfxc/ZQ+NNlu8KfE3w/Jb6X4it7WG51vwB4205vt/gz4h+GjMyCPXfCOvw2mpww+dFb6tZpfaBqhm0bV9StbgA/xWf2vf2Vfi7+xJ+0j8W/2XPjnoh0T4k/CDxXeeG9X8pZjpeu6eUjv/AA54w8O3E8UMt74X8Z+HbvS/FHhu+khhludG1Wze4gtrnzreIA+bqAPR/g/8XPiN8A/in8P/AI1fCLxVqfgj4nfC3xbonjjwN4r0iUR3+ieI/D19DqGnXaK6vBdQGaEQ32n3kU9hqdjLc6dqNtc2N1cW8gB/s0/8Egf+Cm3w5/4Kq/sZ+B/2h/DH9maF8StKEXgj9oD4a2dwXm+Hfxb0mxtpNatbaCeWW7bwj4nhmg8VeBdQmkuDc+HdUg0+8uTr+ka7aWQB+pFABQB/KR/weOfCfVviD/wSR0jxvpcO+D4FftWfB/4j+IphGXMPhzxB4d+I3wcwWHESS+Kfil4VBduC6xx/ecUAf5X1ABQB/S5/wa3f8FKPAf7AH7f9/wCDvjZ4jsfCPwJ/a18Kab8JfFXi/VpzaaH4I+Iela1/avwm8XeI71nFvY+HRqV/4g8Gavqd4sen6FB43HiPVb7T9G0bUrgAH+szHJHLGksTpLFKiyRyRsHjkjcBkdHUlXR1IZWUkMCCCQaAH0AFABQAUAFABQAUAFABQAUAFABQB+Hv/BdX/gjr4Y/4K7/s0aL4T0XX9F+H37SHwY1HV/FPwD+I2uWc9zoIutbs7a28VfDjxw1jDcapB4G8eQ6do5vNW0mC51Xwt4g0TQPElrYaxZ2OqeH9ZAP8xD49f8EWv+CqX7OXi/UvCHxB/YT/AGktSmsLy4tIPEfwy+GHiT4xeBtXjhneOG80Xxv8L7HxT4dv7e7jCXECNeW1/HDMi3thaTh4UAPB/wDh3V/wUG/6MT/bM/8AEXvjZ/8AMV680AJ/w7p/4KD4x/wwn+2Z3z/xi/8AG3knPf8A4Qn3oAX/AId1f8FB/wDoxP8AbL/8Re+Nn/zFUAIf+CdP/BQbr/wwn+2Z1/6Ne+Nvv/1JXfNAB/w7p/4KDZJ/4YT/AGy+n/Rr3xt9/wDqSvf1oA+aviJ8NviN8I/FmpeAviv4A8bfDDx1oyWT6x4M+IfhTXfBPizSk1KzttT059S8OeJLHTtYsVv9OurbULJrqziF1ZXMF3AZIJY5GAOMLAdff17Z9v8AP8wBN3c/3V7HrzQAZ5B9c9j23f4igBAeRk+h7nPy4J6UAKp4GT2JPB9evv780AAbA59v/QR+H60AITnnPZvX+6OP6/8A16AFJ5PPGf6p/jQAm70POH7epyP8aAP7R/8Agyb/AOT6f2sv+zSof/V1eAaAP9K2gAoAa3T/AIEn/oa0Af4LXxqOPi/8VOcf8XI8d/8AqW63/wDr/wAehAPM88ge5P6vn+lACBicZPXH1zu/LpQAuTzz2Y/juPNACE8vz147+hH59P1oAUMSRzwSf0A9f1xQAm7pz09j/dI5/GgBdxOOe/p/uj+p9aAEz79Qc++FH49aAAtkHkfr6j1/z9ewB9BfC79k39qj44+Hbrxf8Ff2aP2gvjB4StdVuNCuvFHwt+DHxG+IPh221y0tbS7utGudb8KeHdV02DVbW0v7G6udOkuVvILe8tZpYliuIWcA9I/4d0/8FBv+jE/2zOpP/Jr3xt9c8/8AFFUAL/w7q/4KDf8ARif7Zn/iL3xt/XPgo0AJ/wAO6f8AgoP/ANGJ/tl9/wDm17429zn/AKEr/PvQAf8ADun/AIKDZz/wwn+2Z/4i98bff/qSvfNAD1/4Jz/8FCHdUT9hL9sxndgir/wy98bMszNhQP8AiiupJAHvQB+zX/BMb/g2D/b8/bI+J/hjVf2lfhZ47/Y//ZosdQsL/wAeeMPivoZ8KfFPxLoUdwJb7wt8L/hhroTxQPEetWq/ZLbxb4v0XSfCHhy3un1wnxJe2Ft4a1MA/wBVP4YfDbwT8G/hx4D+Enw28PWHhP4e/DPwh4d8B+CPDGloyafoHhTwppNromg6Rah2eRorDTLK2txLK7zTmMzTO8sjsQDuqACgAoA/lw/4OV/+CINx/wAFKfgtp/7R/wCzpoVo/wC2f+z74a1C30zRLeGKG6+P3wrtpLnWLv4Wy3RKf8Vp4fvptS1z4W3Nw5trrUdU17wjfeXH4msNX8PgH+VJqml6nomp6joutadfaRrGkX13peraTqlpcWGp6ZqdhcSWl/p2o2N3HFdWV9ZXUUttd2lzFFcW1xFJDNGkiMoAKNABQB+xP7FX/Bev/gqZ+wX4e0fwH8E/2m9c1v4UaEY0034R/GHR9H+LXgXTbGFVWLR/Dx8X2t54r8E6Gm0sujeAvFPhbTxLLNP9n86aSRgD92fA3/B7h+2RptpZR/En9jb9mrxfeRQxJf3XgzxN8T/h/HeSqoEs0FtrOsfEf7GJSCwjaa6EZbhmUAUAd1rf/B8F8frgN/wjf7A/wf0okfIdb+NHjTxAFPqwsPBvhkuM9gyfXvQB8t/FP/g9A/4KbeLoJbL4a/B/9kr4R28kZC6nB4K+InjnxNBKQRvhvPE/xMPhkoPvLHP4PnbcPmlZcoQD8h/2lP8Agvh/wV2/ass7rR/if+298WdG8M3aSW83hT4OyaH8BtCuLGbd5mm6pH8G9I8E3/iOwcMyyQeKNQ1szJtSZ5ERFUA/Im+vr3U7261HUry61DUL+4mu76/vria7vby7uJGlnubq6uHknuLieVmkmmmkeSSRmd2ZiSQD+8D/AIMcf+Sg/wDBR3/sTf2Yf/T38c6AP9C6gAoA/wAW7/gu5/ymG/4KH/8AZy/jj/0K0oA/JigAoA/3nvgF/wAkJ+Cv/ZJfhx/6h2jUAetUAFABQAUAFAH8tX/B4J/yh61T/s5f4H/+g+MKAP8AKcoAKAOqbwJ43TwRF8TX8G+Kl+G9x4quPAkHxBbw9q48ET+N7TSLXxBd+DYvFZs/7Bk8VWug31lrdx4eS/bV4dIvLXUpLNbO4imcA5WgD9PP2NP+Cy3/AAUt/YI07SvDP7NX7V3xC8NfDvR5nksvhN4sbSviZ8KbWG4na5vrPSvAfxD0/wASaH4Yh1GZ5Zb2fwjB4f1GSeWW7jvorx/tFAH7Y+Ev+D0P/gqbocS2/iP4Q/sU+NkCYa71D4Z/F7RtUeQLhXMvh/48afpYBb5pUXRhu6RtCKAPCfjz/wAHcv8AwWB+NHhzVPDXhfxV8CP2dItVVoZta+BXwnuYfE9vZyK6TW2na58WfF3xZn0qSZGx/amlJZa1auqzadqNjMA4AP5yfin8Wvil8cfHev8AxQ+M/wARvG/xX+JHim5S78SePPiL4o1rxl4u1yeKFLeB9T8QeIL3UNUuxbW0UNpaRzXLRWlpDDa2yRW8McagHn1ABQB/Rv8A8G1//BJef/gpN+2pp3j74qeGJdQ/ZJ/Zcv8ARPH/AMXH1Gzd9C+IvjFLk3fw9+Cyyyo1vfxeItRs28QeObILNGvgHRNU0q9k0688VaBcTAH+t+qqiqiKqIihURQFVVUYVVUYCqoAAAAAHAoAdQAUAf4N/wC0h/ycR8ev+y0fFL/1ONdoA8XoA+pf2Gv+T2P2Pf8As6X9n3/1bPhKgD/dToAKACgAoAKACgD/AAaP2h/+S/8Axy/7LD8TP/U11ugDx6gD6T/Yz/5PA/ZS/wCzk/gZ/wCrQ8L0Af7stABQBDcW9vd289pdwQ3VrdQy29zbXESTW9xbzI0c0E8MitHNDNGzRyxSKySIzK6lSQQD/KN/4OP/APght4j/AOCb/wAcNW/aT+Afhi5vv2Hfjj4svLzRE0iymkt/2ePH+tzzX918Jtf8pXSz8HX87XVz8KNamMcUmlRzeDNQZtY8P22p+JQD+X+gAoA7b4dfEr4ifCDxpoHxH+E/jvxh8M/iD4VvU1Lwz448BeJNY8I+LNAv0BVbzR/EOg3lhqunXGxmRpLW6iZ43eNyyOykA/pJ/Zq/4O5P+CuXwLt7LSPiN4o+D37U+g2kKWir8a/htb6Z4pitIkCReR4v+Eeo/DW+vr5dq+Zqfiq18U3lyDI1288zrOgB+jmg/wDB8D8f7e0dPFH7A/we1i/MeI7nQfjP418N2iy8fO9jqHg7xVM8fX90NQjbp++oA5nxB/we7/tY3KTDwt+xL+zxo0jK4gbxB46+JPiVI3IOxpk06Twm06q2C6JJblwCA6E7gAfB/wAXf+Dvb/gsX8SBdJ4M8V/s/fAOOfesJ+FXwQ0vWbi1RshTHN8bdZ+MCvMq9ZXhKl8ukcYwqgH4c/tLf8FAP22/2xrye6/ae/an+OHxptZrj7Unhzxn8QNeu/BGnziTzQ2i/D+1u7TwPoCiQCQR6J4f0+IOFYJuUEAHyBQB/tj/APBGP/lEv/wTh/7My/Z8/wDVbaBQB+mNAH+bz/wdsf8ABZD/AIXV8R7j/gmL+zz4q874T/B7xFbaj+1J4j0W93Wnj/4x6HOtxpXwpW4tZPLvPDXwju1W+8U20kk0F78UhFY3VnaX/wANba5vgD+I2gAoA/sP/wCDTr/gkD/w1b+0A37f/wAdvC/2v9nr9mHxVbx/CXRtZs92m/FP9onTUtdV0zUFhmQrf+GfgzHPp/ii+f8Ad29747vPB9jFLf2uj+K9MjAP9OmgAoAKAP5GP+DrL/gkB/w2T+zgP24fgX4X+2ftL/sr+Fb6XxxpOj2Xm6v8XP2eNPkutZ17TBDChm1HxP8ACia41Pxr4ZjQ/aL3w5deONDhh1TVbrwzZ2wB/l3UAFAH7N/8ENv+Crvi3/glB+2ZoHxLvbjVtV/Zz+KR0rwB+014FsPNuTqngR75307x1oumhjFceN/hffXlz4i8OkIt1qemTeJvB0d3YW3i28vIQD/Y28E+NfCXxJ8G+FPiH4C8RaT4u8D+OvDmi+L/AAd4q0G8i1DRPEnhjxHp1vq+ha7pF9AzQ3mm6rpl3bX1lcxsUmt543HDUAdPQB8U/wDBRz9ku0/bq/YY/af/AGTbi7t9PvvjR8KNe8P+FtTvQGsdJ+IGmNbeJ/hvrGoKUcvp2keP9C8NalqCRhZ3s7WdbeWGcxzIAf4fnivwt4i8DeKPEngrxfo994e8WeD9f1jwt4o0DU4Tb6lofiLw/qNzpOt6PqEBJMF9pmpWlzZXcJJMdxBIhJK0AYFABQB+8/7A/wDwch/8FQv+Cfvg7QvhZ4J+J3hf43/BrwxbWun+GPhZ+0Z4f1Hx9pPhPSLRfJi0fwn4r0fxB4T+I+h6Na2ojttK8PJ4yuPC+iRW8EelaDbQiaGcA/U/V/8Ag9m/4KBzafFHoP7K37HOm6qIyJ73V9P+Net6fJLzh4tMsvi34fuYY+mY31edup83nAAPjP42f8Hb3/BZD4uaZLpXhb4hfBP9nuK4WSO5u/gn8GNJbU5YJchootS+MWq/F+805gpKx3mkzafqMPDw3kcoEgAP6of+DRT9q39pf9rn9nb9sz4gftPfHf4qfHjxhYftB+E9N0nWvih4113xdLoGlTfDu0vZdH8NWurXlxY+GdFe8lluzo2gWunaX9qlluBaCaR3YA/rtoAKACgAoAKACgAoAKACgAoAaUXngjJydrMuSepO0jJPqcmgBNg9X/7+Sf8AxVABsHq//fyT/wCKoANg9X/7+Sf/ABVABsHq/wD38k/+KoAQoMHl+h/5aSf/ABVAH+RZ/wAHUTE/8Fuv2syxLY0L9ncDezPgD9nf4ahQCxJCqAAoBwAMAY4oA/nk+btj8c98/wBDz75oATnoMdB64xyP59PUUAHORwM+2ep3fp1zQAmTnoO3TPUrx+H9KAFBJHGO+OvXOT+H9eKAAZI4x+OQeg6d+/5fXkAOe+P4s9fbr+Y+goAD17Z/HuV6/l/L1oATnvj+Lu3rg559f8aAP7R/+DJv/k+n9rL/ALNKh/8AV1eAaAP9K2gAoAa3T/gSf+hrQB/gt/Gn/kr/AMVOn/JR/HfX/sbdb/z9M0AeZd+3U+uf4v8A69AB6fd7Z655bsfT+uaAD16chh3z1PJ9vfsaAE5y3A9TnPufz9fXnNACjqM4zk9M55H6n1z25oATnjhefr6Hr+HHegBfrjP4+q/mePzx68gCev3f4u5/ug8c/wCR0oACCAc46ds56jnn9T9M5oA/1F/+DMvLf8Eq/iepZ9o/bW+K5Ch3ABPwr+B+SAGABbA3Efe2rnO1cAH9bWwer/8AfyT/AOKoANg9X/7+Sf8AxVABsHq//fyT/wCKoANg9X/7+Sf/ABVABsHq/wD38k/+KoAcFAyQOT1Pc46ZPU4HqTQAtABQAUAFABQB/K3/AMFzP+Daf4T/APBSC58R/tM/swX3hz4GftotYvda+l5bfYPhV+0LcWsWIE+ISabazXXhf4gvGiW1l8TNMs7/APtKNI9O8aaPqqGw8QeHQD/M9/am/Y//AGmf2J/ijqPwa/an+DPjb4L/ABC0/wA2WLSvFmmhNP1/T4pjB/bng7xNYyXvhjxt4clmVooPEfhLWNZ0SeZJIY79popY0APm2gAoAKACgAoAKACgD/QU/wCDJT4NfF3wc37dHxW8XfDDx/4W+GXxK8Nfs9af8OviB4i8I69ong7x7eeHdV+MNxr8HgzxFqVhbaV4obRIdY0l9WbRLq+TT/7TsRdtE11CHAP75KACgD/Fu/4Luf8AKYb/AIKH/wDZy/jj/wBCtKAPyYoAKAP9574Bf8kJ+Cv/AGSX4cf+odo1AHrVABQAUAFABQB/LV/weCf8oetU/wCzl/gf/wCg+MKAP8pygAoA/vo/4NU/2dPgT/wUB/4Jf/8ABRn9hn9o3wwniz4aax8evBfjCaK3khtvEXhDxB42+Gdto+gePvBWqzW92dA8ZeHNQ+Gcd9omrLb3EDvbTadqtnqmiXuqaVegH82v/BXf/giP+1X/AMEmvibqC+NNE1L4l/sy6/rktp8KP2l/DmkTDwnrtvcmSfTfDfjy2t5Lz/hXfxGitlaO58OazcCx1uW0v77wbqviHTLS7ntAD8YaACgAoAKACgD9jP8Agkn/AMEVP2r/APgrJ8UbGx+HehX/AMPP2dPD+uQWfxb/AGlvE2kTnwV4TtIfLuNR0LwjDNLZf8LD+I8lnJGLDwhoV0UsJr3Tr3xfqfhnQ7pNUYA/1vf2Jv2LfgJ/wT+/Zx8A/swfs4+Fv+Eb+HngW0d5729a3uvFPjfxTfrE3iLx/wCOtZgtrT+3fGPie7iS51S/+z21pa28VjomiWOleHdJ0fSLAA+r6ACgAoA/wb/2kP8Ak4j49f8AZaPil/6nGu0AeL0AfUv7DX/J7H7Hv/Z0v7Pv/q2fCVAH+6nQAUAFABQAUAFAH+DR+0P/AMl/+OX/AGWH4mf+prrdAHj1AH0n+xn/AMngfspf9nJ/Az/1aHhegD/dloAKACgDg/ij8Lvh18bPh54x+E3xc8F+HfiL8NPiBoV94Z8aeCfFmmW+seHvEeh6jH5d1p+pWF0jxSoflmglXZcWl1FBeWk0F3bwzRgH+a//AMFkP+DUT49fsxav4m+PH/BOvRfFn7Rv7Ok8t/rerfBa1D698e/g7alpLmSx0TTogdR+M/gyzz5Ol3eg2918SLC1aC11vw/4hjsNR8aXYB/HZe2V5p15d6fqNpc2GoWFzPZX1jewS2t5ZXlrK8FzaXdtOqT29zbzo8M8EyJLDKjxyKrqQACtQAUAFABQAUAFAG/4W8KeKPHPiHSPCPgrw3r/AIw8WeIL2LTdB8MeFtH1HxB4h1vUZ8iGw0jRdJt7vUtSvZiD5VrZ2008mDsQ4oA/20/+CTvgTxp8MP8AgmT+wR8O/iN4U8QeBfHvgr9kz4GeG/GHgzxZpN7oPifwv4i0n4faHaaroXiDRNSht9R0jWNMu45bTUNNv7eC8srqKW3uYYpo3RQD87/+Din/AILAWH/BLr9kS48O/DDXLQftg/tG2GueD/gZYRSQ3F98PtGSBLTxj8cNSs33pFb+DIL2Ky8GR3qPDrHj/UNIP2LVdE0HxVFagH+RRqGoX+rX97quq3t3qeqand3OoalqWoXM15f6hf3kz3N5e3t5cvJcXd3d3Ekk9zczySTTzSPLK7u7MQCpQB9qf8E9v2G/i1/wUY/a2+Ev7J/wdtni1z4ha0snifxXNZy3ej/Dj4d6QUvPHHxF8QiN4lGl+GNFE09vayXNrJruuTaP4Y0+Y6vrmnwygH+1J+yt+zL8Jf2Nv2efhN+zH8DdAXw58MPg74RsPCfhuzbynv79oTJd6z4k166higTUfE/i3XbrU/E/ijVfJibVPEGrajftHGbjYoB9AUAFABQA10WRWR1V0dWR0cBldWBDKynIZWBIYEEEEg5oA/yZf+DmH/gkG3/BN/8Aa4k+Mfwd8MtYfsg/tTaxrXij4eQ6baldH+FPxLLNqnjv4Nv5KC303S4pbiTxX8NbZ1tYpPB95deHNNjvX8B6xesAfzR0AFAH99P/AAaMf8FkvsF1bf8ABKn9ovxViyv5tX179jjxZrt7hLS/la61vxd8AZ7y4fasWoyHUfGXwyimKY1E+K/CcV1NNqPgrRYgD/QPoAKAP8+//g6T/wCCCHjXVPHHin/gpd+xT8Nr7xRp/iWDUPEP7YPwo8F2H2rW9K8QWiCe8/aB8LeHLNTd6xp2vWolm+Ltjo9tNqOm6xaP8R7i11Cz1zxrq2ggH8C9ABQAUAFABQB/pF/8GRX/ACaJ+2p/2cf4O/8AVZWNAH9ttABQAUAFABQAUAFABQAUAFABQAUAFABQAUAIeh+hoA/yKf8Ag6hz/wAPuv2tMdf7D/Z4Pv8A8m8fDX/9dAH88hb0K/if/r/WgAB68j+HnPHfPOev/wBbNACZPqPzyP4vfpyM0AHIPJ4+uegOf16+9AACcDkZ5+8T6jr+H4/rQAZPrz05PHQdfxB/HPvQAE98jkN3/LoevH/oWKADPvz6Z56qfp0z+H40AGT6j+LPPHJ47/l7dKAP7Rv+DJv/AJPp/ay/7NKh/wDV1eAaAP8AStoAKAGt0/4En/oa0Af4LXxpOPi/8VOf+aj+O/8A1Ldb/wAj3xQB5nnkcjGTnnnvjv05H14oAM+/p0OR1JPJ56DmgAz156hu59cj9D9cYxQAZPzYPXp+ucc/yzzigBc9CSO+efw4HpkHrn16mgBM9OenXnnoc559SOvfr2oAM+pX3wT7e/8Ak/U0AGevPqBzyeOPr3z/ALVAAxOOvJGePqM/h6e2cmgD/UW/4Myv+UVnxQ/7PV+K/wD6qv4H0Af1u0AFABQAUAFABQAUAFABQAUAFABQB4V+0J+zD+zx+1j4Bu/hd+0r8F/hx8b/AAFeea//AAjnxH8K6V4ltdPu5Y/K/tTQri/t5L/w5rkKY+ya9oF3pus2TqktnfwSorgA/lQ/az/4Mwf2Fvipc6jr/wCyh8cPi9+ynrN5NNPD4U1+2t/j58LbFCzSRWWl6Z4i1jwn8SrJWLGBrzVPin4k8mIRSJYyPFIlyAfhT8XP+DL7/gpb4QvbuX4T/GX9lL4xaFHu+w+f4u8f/DnxbdBScfadB134fal4asy67doj8d3oDl1dkVVkcA+MNZ/4NS/+C3ulySpY/su+DvEaxuypLo37Rn7PkEc4UkCSIeIfiRoMoV/vKJ44XAPzojZFAFjSP+DUX/gtzqW37b+zR4G8P7sZ/tf9or4DT7M9d39g+P8AW8477N/tmgD6I+HP/Bm9/wAFaPGM6f8ACX+If2UPhLaBx57+L/i54p1698rI3NaWvw5+GnjW2nmwTsiudRsY2IIeePgkA/T34Af8GQRXUbbUP2pv26/N0mMxfbPCXwA+Fn2fUbtScz/ZviJ8RdaurbTygBji834X6kJS/nOYvL8mUA/os/Y5/wCDcT/gkp+xdqmmeK/CX7N9r8ZviJpPkPY/EP8AaW1X/hcerW1zbMJLfUrDwnqljp/wq0bWbecC5ttb0L4eaXq9pcBHtb2ERRLGAfuZDDFbxRQQRRwQQRpDDDCixxQxRqEjiijQBI440AREQBVUBVAAAoAkoAKAP4t/27v+DQb/AIbY/bD/AGiP2sP+Hhf/AArT/hffxM1z4i/8ID/wyb/wmf8Awin9tGE/2P8A8JT/AMNL+FP7d+zeV/yEP+Ec0fzt3/HjFjkA+S/+IGP/AKyif+aT/wD5W9AB/wAQMf8A1lE/80n/APyt6AP7z/APhb/hB/AngrwV9u/tT/hD/CXhzwt/af2b7F/aP/CP6PZ6T9u+x/aLv7J9r+yfaPs32u68jzPK+0TbPMYA62gAoAKACgAoA/lq/wCDwT/lD1qn/Zy/wP8A/QfGFAH+U5QAUAf3t/8ABjf4okg8V/8ABSHwU7s0Wp+Hv2W/FEEZOVik0LUvj1pN06DPDTr4is1lIHzC3hBPyjIB/fn448C+Cfib4S1/wD8SPB/hfx/4F8V6dNo/ijwZ410DSvFHhXxHpNzj7Rpmu+H9btb7SdWsJtqmW0v7SeByqlkJUEAH8l37c3/BnV+wj+0Bqes+Nv2S/iL42/Yy8Z6rcz38vhK200fFz4HPcTM080em+DNd1vQPGfhQXdwzqq6P8RLjw5o1u6RaR4OitraKzYA/nM+Mf/Bm9/wVX8A3l+/wy8T/ALMfx30ZJHOlv4a+Jmt+CPEl3bg4Q6jo3xI8HeGtD027bGWt7Xxhq9sgK4v3O4KAfK7f8Gqv/BcQXotR+yX4beA9dSX9o/8AZr+xDnHMbfFhdR568aeeOvPBAPp34P8A/BnJ/wAFYPH97ZH4ka1+zL8CdIeZf7Tl8W/FPVfGWvWtrn94+n6R8MfCHi/SNRuwOY7a68UaTbyc77+E4yAf0XfsN/8ABnD+w78CNT0jxr+198T/ABt+2P4t0y5t7+LwVFprfB34IpPEyzpBq/hrRNd1/wAdeLhaXKIA178QNH0DV7dZYNY8IXFtcyWiAH9bngH4feA/hV4O8P8Aw8+GPgvwp8O/APhPTotI8L+CfA/h/SvCvhTw7pcBYw6donh/Q7Sx0rS7ONmdlt7K1hiDu77dzsSAdfQAUAFABQB/Bv8AEj/gyS/4WD8RPHvj7/h5p/ZH/Cb+NPFPi/8Asr/hjL7f/Zn/AAkuuX2tf2f9u/4ausvtv2L7b9m+1/Y7T7T5fnfZoN/lKAcX/wAQMf8A1lE/80n/APyt6APU/gb/AMGV3/Cl/jZ8HvjF/wAPKv8AhJP+FT/FP4ffEv8A4R3/AIY4/sf+3/8AhBPFukeKf7F/tf8A4ao1X+yv7V/sr7D/AGl/ZmpfYfP+1fYLzyvs8gB/dTQAUAFABQAUAFAH8GnxD/4Mj/8AhPfH/jnxz/w81/sr/hNPGPibxZ/Zf/DGP27+zf8AhI9avdY+wfbv+Gr7P7Z9j+2fZ/tX2S1+0eX532aDf5SgHHf8QMf/AFlE/wDNJ/8A8regD0r4M/8ABlN/wqP4wfCn4r/8PLf+Eg/4Vj8SvAvxD/sH/hjb+yf7c/4QvxRpfiT+yP7U/wCGqtS/s3+0v7N+xf2h/Z2ofY/P+0/Yrry/IkAP7sqACgAoAKACgD8p/wBu3/gij/wTc/4KKG/1n9on9nPw2nxNvVJHxv8Ahk7fDP4wifbsjuNV8XeGo7dPGv2eMulpZfETTfGGlWm9nt9Pjm2yKAfywftIf8GQ0L3up6r+yJ+3E9vpzmQ6P4F/aO+HIu7y3HzNGNR+KvwzvLSK63ZWNzb/AActCm0yjzS4iQA/JH4hf8Gfv/BYbwZJKnhvR/2bPi2iOVSb4f8AxwXTFmXdgSIvxU8KfDSRQR82JURgOME0AeFS/wDBqz/wXGju1t1/ZF8PzQnOb+P9pH9mUWq4PVkm+LsV8c9Rts2OM5wcAgHc6N/waWf8Fp9UaNb74K/Cbw4HKhn1n9oH4YTrCGIBaT/hHtZ15yFzlvKWViAdoY4BAPsn4Y/8GVP/AAUR8RfZ7j4qftGfsk/DOym2mW10DWPip8R/ENoD98XFgPhv4P0F5F52ra+KrmN8czJQB+yH7M//AAZVfsX+BP7P1X9qb9pf43/tB6vb+VNceH/h9pfh74FeArqQ4aay1CFn+JPji+tUyYo7vSvGvhe6m2i4aK33/ZkAP6cP2P8A/gnH+w9+wR4f/sD9kr9mv4afB6Sa0FjqfizStJk1v4k+IbUFW8jxP8UfFNxrnxE8SW4kXzY7PWfE17ZW0jyG0t4A7LQB9sUAfx1/8FHf+DV74xf8FLf2tfiX+1d8Zv8AgqP/AGfqXi+7j0rwR4Ftf2OZ9U0L4V/DLRZLiPwb8OPDtzN+1fYi4stCs7ia51TVI9N0xvE3inUfEHiy70601DXruFQD4X/4gY/+son/AJpP/wDlb0AH/EDH/wBZRP8AzSf/APK3oA/og/4Im/8ABCn4Rf8ABG/wz8Wbyx+J3/DQ/wAcvi/qVlZ698ab/wCHEHwzm0n4b6Mlvc6N8OPDnhb/AITb4iy6Vp7a/wDbvEXibUo/FLN4qvx4fW+sIIvCmkbAD93KACgAoAKACgD4o/4KGfsK/CH/AIKPfsl/FX9k74zRfZdC8f6ULjwv4xttPh1HXPhn8RNH8y78FfEfw5DNPaGTU/DOrFZLrT0v9Pj8RaDc614V1C8i0nXdQDgH8bX/ABAx/wDWUT/zSf8A/K3oAP8AiBj/AOson/mk/wD+VvQBv+Ff+DI3xJ4G8UeHPG3g3/grDqvhfxf4P17SPFHhXxLoX7Gk+m634e8R6BqFvquia5o+o2v7Xcd1YappWp2ltf2F7byJPa3UEU8TrIisAD+6H4XaJ4+8NfDfwL4e+KnjrSvid8SdD8KaHpPjn4jaJ4MHw70rx14o0/T4LXWPFln4EXxH4uj8JR6/exS6m2gQeJdYtdNluZLa0u2tkiRADvKACgD+aX/go7/wa0/8E7P269S8RfEf4a6fqX7G3x68Q3t5q+p+O/g3pFnqHw78Ta1fzPcXmpeNvglfX2leGry4uZ5ri8u7zwHrHw31fU9Sne+1vVdVkLo4B/LJ8d/+DML/AIKP+A9Rlk+Bnxi/Zr+P3hsyvHbPea/4p+EfjQqu5lnvvDfiPw/rnhW2ikXaoFp8RdSmWVirQiJfPYA+KtX/AODUz/gt9pt6lrZ/st+D9fgZiralpP7Rn7PUNlGB/G6a78StF1Eq3YJYO/qg5wAej+Bf+DRT/gsv4uvY7XxB8P8A4EfC6B9u7UvHXx58MahZRbjz5ifDO1+IuonZ1fyrCXI+5vPFAH6i/s+f8GQ3xXv57O+/ar/bh+HvhS2ilR9Q8Mfs+/DrxJ8QJ9Qh3DzYLPx18Rrr4aR6PLsyUu5vh5rqBsBrMg7gAf2Of8Ezf+CWH7Lv/BKP4QeJfg/+zGvxCv7Hxz4js/F/jzxZ8TfFkfijxV4s8SWOkwaLbahdJpmleHvDGkRQWEAijsvDnhvR7ZtzSXKXM2JQAfpFQAUAFABQAUAFABQAUAFABQAUAFABQAUAFACHofoaAP8AIp/4Oof+U3X7WnJH/Ej/AGeOn/ZvHw19xQB/PIc9vfoM9/c9f580AHPqc4XqPX2z+dACZPqc/Tv83vjt+PFAC8569+/rtz6/j9fzoATJwOSeD2yev19/60AAzjjPbtnsvvQAEn17N2/+v+Xrx60AKTz17j+a/wCP60AJk8cn+Ptz19P8+negD+0b/gyb/wCT6f2sv+zSof8A1dXgGgD/AEraACgBrdP+BJ/6GKAP8Fv40Z/4XB8VMf8ARSPHfv8A8zdrX+TQB5lzkderduM5bv6+1AByR17jqMc7vr/n86AFz15/vn8j1oAQk/Pye34fTn8z+NAC5ORknn29u/PHf8c9qAEGfl+g/wDQT780AAJ7569wB6f4/kSe3IAc/N/wLPHsPf8ALrkUABzg5PYdsdT9fzoA/wBRb/gzK/5RWfFD/s9X4r/+qr+B9AH9btABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQB/LV/weCf8oetU/7OX+B//oPjCgD/ACnKACgD+6L/AIMfP+S7ft/f9kl+CH/qY+O6AP8ARWoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKAEPQ/Q0Af5FP/B1D/ym6/a0ycf8SP8AZ47Z/wCbePhrQB/PESD1K9+xPf1/z696ADj26Dkgnpn8fr6dOaAE4PGQevb/AHj+GM9O/H4AC5Ge2evTtt/ljnHrx70AAxgf4HJy2e2e4wB9TQAcdD39iT0Hp7YJ/wDrZIAce3RucEdcZ/Q8eucccZAAkZznv9f7v1z09e59KAD5fy3dj3Pf8On9DQB+in/BOH/gqB+05/wS1+Jfjz4r/svP8O08V/EbwGnw68RH4i+D5fGOm/8ACOp4j0rxSPsFnHrGim1vv7T0i03XLTzL9n8yIwbykyAH7Df8RgX/AAV5/wCe/wCy9/4Yy5/+bugBf+IwL/grz/z3/Ze/8MZc/wDzd0AA/wCDwP8A4K8ghvP/AGXvlIb/AJIZdgHDAjJHjwEA+oIPdSOoAP5fvEevX3inxBrviXVTb/2l4g1nVNc1D7NCYbf7dq9/c6ld+RAGbyYftN1N5UQZhHFtTc2NxAMbvnvk/T+LOT+f5e/AAgxwMgnjHHPXPXt/k98UAHryOjfqT378g4HfrQAHaS3v7Z6DnB+vOTjP60ALxkcjgn1H1yT3Hr3oATK8dP8Avk+h6+vJ7f8A16ADj1HX3GOR1zk9QB+J9KADjn8ex7gE49PUZ65I96AA4wcY/Ig8H1PXnGe/egD/AFF/+DMr/lFZ8UP+z1fiv/6qv4H0Af1u0AFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFAH8tX/B4J/yh61T/s5f4H/+g+MKAP8AKcoAKAP7ov8Agx8/5Lt+39/2SX4If+pj47oA/wBFagAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAQ9D9DQB/kU/8HUP/Kbr9rTk/wDID/Z46df+TePhr70Afzxt9SOv8/cj16/4jIAde56L69/x6n/9WSaAE/E9Dz/33nvz+f8AOgBe/U5z7/3OvXr+p9aAE7ZyenX/AIF9fpn+dAByR1PbPvlV65I/X+Z5AD8T/Gefpjpn6+/86AFPX3z9O6e+aAE9OT0Y9SfUdz/Ln1POaAD05P8AD79hjPPHOT+PGaADnJ5OcHsfUdOc/wBPegAx82cn73+e/wCHrjnGKAFPXqf8vzzQAmODyeo9fT6/17DHUUALn5hz3PH4t7/0/GgBB2OSeR69d3Xr1/P8yKAF9evR/wD0I579f85oAQ/xcng+/fPv/n3zQAo6jk9SR+X17dvX9SAJjpyeg9ePlPv/AJ6DvQAD6k88/mvuc/8A1z+IAc+pyN38h3ye/P19KAAjAPJ6D8ifXJoA/wBRf/gzK/5RWfFD/s9X4r/+qr+B9AH9btABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQB/LV/weCf8oetU/7OX+B//oPjCgD/ACnKACgD+6L/AIMfP+S7ft/f9kl+CH/qY+O6AP8ARWoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKAA8gj1oA/yZP+Ds/wCHfiPwZ/wWa+MvibWbC5ttJ+LXwq+Afj7wfdTRFYdT0PT/AIbaX8Nr+4tpCNsiWvinwFr+nzAHcktuQ+AylgD+ac/7v6A/4/5P1IAEx14/u8Hn1/z/ADxzgAMdsHp+P8ftnn6UAL36d/Qf3OnX9OnvQAg6Dg/5bPPBz+X4HnAAYyOmenbP8K/U/ofw60AGPb+9wPfH19f8M8ZAA8547/h1X3Pp6+vPoAGOnB/j6d+39e4Ht6EAOfTpjtyDgfT8f129aAFI5OB1HXAwec569+vXPqPUAMc5x/ETyP6+nf8AXJPFAAfp+ffLZ/zkj8eoAExweO47e3+c59TnGTgAX+IH3b+bf56/40AIOg47jk4z9716/p3oAX14PRh78k/5/lnnAAh/i45/D3+uPc859uoAF5yDg9Sew6gdfr74Pt2oATHTjqB2Hoffn1659cY5AD8D1z9eVPoPTPPoc85wAGOvH97t04H+ep/HrQAYJzxycAYGMknj8z7c9wvcA/1VP+DPn4d+IvBX/BIz/hI9csbmzsPi1+0/8aPiB4RlnjMaal4a0/TfAnw1bUbfcAXt5PEngLxHaJJ0drKQoSuCQD+qCgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoA/lq/4PBP+UPWqf9nL/A//ANB8YUAf5TlABQB/dF/wY+f8l2/b+/7JL8EP/Ux8d0Af6K1ABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAfiV/wAFrf8Agix8IP8Agr58GPD+kaj4hj+FP7RHwmXWrz4K/GWHSBq9tax60kEus/D74g6TBJbXuv8Aw98SXdlY3haxuote8Ia9bQeIvD73MMuv+HvEgB/n1fFL/g1b/wCC03w78S3uh6B+zX4Y+L2k29xLDZ+M/hj8bvhJJ4d1eKNmUXdpaePPFPgXxZZxSbcrDrXhvTrpchWiOC1AHmn/ABDN/wDBb3/oxjxD/wCHl/Z2/wDntd+p9TzQAf8AEM3/AMFvf+jGPEP/AIeX9nXr6/8AJWu3b0wPSgA/4hm/+C3v/RjHiH/w8v7Ov5/8laznPP15oAP+IZv/AILe/wDRjHiH/wAPL+zt1z1/5K117fTigA/4hm/+C33/AEYx4h/8PL+zr+ufi1+P1JPegD8a/jH8IPiN8Afir8Q/gl8XfDkvg/4n/Crxfr3gPx94Wn1DStVm8P8AizwzfS6brWkyanoV/qWjXz2N9FJC13pmoXllMV8y3uZoislAHmvPXnP/AOr2B6Z7dz3IyAKcn179sc9Rj+fX64NACZIH8j/P16nPXr1G7OKAA5I75/HPUc//AFwO56ZxQAvt7/pnp6dOevTtQAnQ/wCT3P8ATj1xx1wKAA55P5Hn0PT6nH4kdeKADHPsc8fnj+Y4I9PQ4ADnpyc4znv8xzk8jp79OMHsAffv7Ff/AAS7/bs/4KIab8QtX/Y5+Amo/GfTvhXe+G9O8e3Fj42+G3hIeH7zxfb6xd+HYnj8e+MPC8t82o22g6rIj6Yl6lsLQrdtA0sAlAPuH/iGc/4Lff8ARjHiH/w8n7Ov/wA9mgA/4hm/+C3vf9hfxCfr8Zf2dufr/wAXa/H680AH/EM5/wAFvv8AoxjxD/4eT9nX/wCezQAf8Qzf/Bb3/oxjxCf+6y/s6/8Az2f85PqaAD/iGb/4Le/9GMeIf/Dy/s7f/Pa7dR780AfpX+wR/wAGff7dHxa+I/h/Vf2577w1+y18FNPvYLzxTo3h/wAaeE/iT8bfFWnxSLLJo3hGz8H3PiPwL4Ul1ONJbJ/FPinxBeTeH3ljv7bwd4gkiFo4B/pO/Bn4PfDj9n34U/D34JfCHwppvgj4Y/CzwjofgfwP4V0lXFlovhzw9Yx2GnWgmmaS7vrpo4zcajqmoTXOp6tqM93qmpXVzf3lxPIAem0AFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFAH8tX/B4J/wAoetU/7OX+B/8A6D4woA/ynKACgD+6L/gx8/5Lt+39/wBkl+CH/qY+O6AP9FagAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgBCoPUA/UA/wA6AE2L/dX/AL5FABsX+6v/AHyKADYv91f++RQAbF/ur/3yKADYn91f++RQB/ij/wDBaQf8bZ/+CjP/AGeT8f8A1/6H3VPT/P40AfmN7/r36r6ZHb37deaAE9BgcBv7349vz6+3NAB/9bPXsB6jt1GSP9qgAOTn3HX5s4znsMH8M98HHFAC85/HP8XX67fz5xjt3oADn/O7+9n06/nnjjFACc4/EdN3p/u5/wAjOe4AvcHjqfX1bjOMf1oABnj8P73r7jucd+oHagD/AEM/+DHgA/Db/govkA/8Vt+zJ1H/AFLnxm9f59+tAH932xf7q/8AfIoANi/3V/75FABsX+6v/fIoANi/3V/75FABsX+6v/fIoAcAB0GPpQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQB+WP/AAWG/wCCasv/AAVd/Y6uv2T4vjNH8CHufiZ4H+In/CeSfD1viaqDwaNYB0j/AIRhfG3gAsdR/tbi/wD+EgX7J5H/AB53Pm/uwD+Ub/iBmvv+kndp/wCIaTf/AEVFAB/xAzX3/STu0/8AENJv/oqKAP3W/wCCHP8AwQKuP+CNPjz9oDxrN+1ZD+0WPjn4S8D+Fl02L4IP8JT4YPg3Wde1Y3xvH+LnxK/tn+0f7b8gWwtdK+yfZvN+0XPneXEAf0Y0AFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAf4ov8AwWk/5Sz/APBRrP8A0eT8f/8A1PdU/pn/ABoA/MY9fTnv/wAB75Pt/XvkATg9x/F+H6jr3yfpgcgAUfUdvqcYOP5YwfqTzQAHHJyffkZHPTOfU/8A1+xADj15znqM56Z69fXtj+HNAB+P5/73+POcYzjoOKADjnnuOhHp9evHHOOmckGgA79ecn69W/n3yMcn2AAAY459OMjHX6k/r168cUAf6Gn/AAY7/wDJN/8Agov/ANjr+zJ/6jfxmoA/u/oAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKAP8AFF/4LSf8pZ/+CjX/AGeT8f8A/wBT3VKAPzFJ5J9+/wBU70AGQe3Zsc+uc8Y/LP60AGf129+eAPbn8+DycA0AGeSe+PUdMj2wP1Pr2oAM8/8AAj375+np+GOPvUABP9T1/wBv/PJ/xoAM8Hp1Hf29+e3f8ehoAUfeHrk/zb/PX0oAQHgDscdSP73p1NAH+hr/AMGO/wDyTf8A4KL/APY6/syf+o38Zs0Af3f0AFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFAH+KL/wWj/5S0f8FGucf8Zk/H/r/wBj7qn/AOv9fqAfmOfbHXp+K+3uT+INADefUfxenb8PXk9c9aAF5yeR2z05yB7c5/Cg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BQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFAH/2Q==", - "attach_logo": "logo-2013-color-small.png,data:image/png;base64,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", - "attach_profile": "rushabh.jpeg,data:image/jpeg;base64,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", - "company_abbr": "WN", - "company_name": "Web Notes", - "company_tagline": "Open Source ERP", - "country": "India", - "currency": "INR", - "customer_1": "RIGPL", - "customer_2": "Mahesh Engg", - "customer_contact_1": "Aditya Duggal", - "customer_contact_2": "Mahesh Malani", - "first_name": "Rushabh", - "fy_start": "1st Apr", - "item_1": "Enterprise", - "item_2": "Small Business", - "item_3": "Solo", - "item_buy_1": "Adwords", - "item_buy_2": "Server Hosting", - "item_img_1": "logo-2013-color-small.png,data:image/png;base64,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", - "last_name": "Mehta", - "tax_1": "Service Tax", - "tax_rate_1": "12.5", - "timezone": "Asia/Calcutta" +"attach_letterhead": "erpnext.jpg,data:image/jpeg;base64,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WVpjZGVmZ2hpanN0dXZ3eHl6goOEhYaHiImKkpOUlZaXmJmaoqOkpaanqKmqsrO0tba3uLm6wsPExcbHyMnK0tPU1dbX2Nna4uPk5ebn6Onq8vP09fb3+Pn6/9oADAMBAAIRAxEAPwD+/igAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgBGZVBZmCgAsxYgAKvLMSeAAOSTwO9AHxV4x/4KU/8E6Ph5rl74Y+IH7ff7FPgbxLps8ttqPh7xj+1R8C/DOuWFzA2ya3vdJ1rx3ZX9rPC/ySxT28ckbHa6g8UAcv/wAPYf8Agln/ANJK/wBgH/xMj9nX8f8Amo1ACf8AD2H/AIJZf9JLP2AP/EyP2de//dRu+f1oAX/h7D/wSz/6SV/sA/8AiZH7Ov8A88agA/4ew/8ABLP/AKSV/sA/+Jkfs7f/ADxqAD/h7D/wSz7/APBSv9gH/wATI/Z1/wDnjUAH/D2H/gln/wBJK/2AeOv/ABmR+zrx/wCZGoAP+HsP/BLP/pJX+wD/AOJkfs6//PGoA+hvg1+1N+zH+0al7J+z3+0b8B/jummxLcai/wAGvi98PviglhA7KqTXreCPEOuC1idnVVknKIzMoDEsMgHvHXmgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAQkKCx6AEn6Dk0Af5wP/B1n/wAFovjN4n/aI8a/8E0v2evHOs+APgv8I7LRtO/aI1jwfqt7pGs/GL4ka/olh4ivPAmra1YPbXx+HHgDSdW03StS8L2s9taeI/Gs2vt4ni1Wz0LQIbUA/iMbnOV/75VRnkf3QM/U89SeaAGjrnB6senXI/yPegAHB6HkL+HH+c/jQApJOcqeAR9ckd/8+tAC55xg9euPf/Jz/wDroARuexPH/sw4/HH5c80AGfvHDc+31/yT7/mAL3A56k5xx/F/n/8AXQB6F8Kfi18TfgZ4/wDDHxU+Dvjvxb8MviN4N1ODV/C/jbwNruoeGfE+h39vIHjnsNY0qa3uowwXy7i3leW0u4Ge2vLe4tpZYmAP9ef/AIN/v+CpWs/8FUP2FdM+JXxLTS7b9oX4P+Kp/g98dl0i1i03T/EviPTdG0zW/DvxM03R7eNLXSbP4heG9St77UdPsUt9MsvGGm+LLPRrKz0a3sLaIA/cmgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgBCMgg9Dwfcd/wA6AP8AFM/4LVzzXH/BWv8A4KLvPI8rr+2J8d4VZzkiK28a6hbW8YP92GCGKJB/CiKO1AH5gc4P178Dkr1B555+vP8AeoAQZz/30Oo3Hjue+P0oAXn+R65PQc8fr/eHSgA556dPoOvcdc46n8KADnrjv3Pqf5eg659aAA5//Wf9rv6jB/DJHegBOfm6Z4789O/9emRmgBecj6nvx1bt6/5NABzx069zk/e556env2oA/wBDj/gx5mmf4Yf8FErdpGMEPjv9mqeKInKRzT+GPi/FPIo7PLHbQI57rEg/hoA/u7oAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKAP8AFF/4LS/8paf+CjPr/wANkfH3/wBTvVPf/wDX60AfmMc4Of8A638PU8H1/wA4oAQZyPXLc8dcc9+oP4GgAGc47kLnt0A98nvnj/64ApyScjsR147d+OvvjjmgAyc49we3r9c/Q9c8HrQAN7+/6sMDr7df60AHPzevGenp356EfzPXFABzkdcZPp1+b3z/AJ9aADnAHvknj+96e/8AkmgD/Q0/4Md/+Sb/APBRf/sdf2ZP/Ub+M1AH939ABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQB/ijf8ABaX/AJS0/wDBRn/s8j4+8/8Ac+ap3/zzQB+Y3+Prx1Ht/TqT60AIM+p/i53c+nPH5dcGgBec9+MdT+PoefXnoe+RQAvPX29ePr06/gaADBz1PXPX8x06fj+XWgBDn3/P1P8AnHXjIoAOeRz25z/9bvxnPqT9QA7g5PUjrx3P+fT8KADkfn1J56/5789OtAH+hn/wY7/8k3/4KL/9jr+zJ/6jfxmoA/u/oAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKAP8UX/AILS/wDKWn/gozxn/jMj4+9s/wDM+ap+fNAH5jEdeP8Ax0H+76/j+vpQAgHPT1/g/L3/AK9jQAd+hxx/APxoAO7cHv8AwD1/X/JoACOenf8AuZH59f8APFACkdePX+EH+L/D9OaAE7Hj0/gH4/8A1/060ALjnoOp/g7c9+n4/ie9ABj2/wDHPf8AT8e3PWgD/Q0/4Md/+Sb/APBRf/sdf2ZP/Ub+M3+fegD+7+gAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoA/xRf+C0v/KWn/goz/2eR8fffr481X/P55oA/Mc85P8AMH1HXuenP/6qAGjqOB1bnB75xn2Pbnp34NAC4Oc46Y7ZPAHTk/j+mTQAYPXA5z29wfm75/Dr3oAMHrhfXpz/ACz75657UABHt+nqwPPf/HnPNAAAeRgdeuODj/PPpk0AHcH/AGj2OepOeme/596ADHTgdR7H72eOvGPf1zQB/oaf8GO//JN/+Ci//Y6/syf+o38ZqAP7v6ACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKAMzWda0jw7pOp69r+qadomiaLp97q+saxq99a6ZpWk6VptvJeajqep6jfTQWWn6fY2sUtzeX15PDa2sEbzTyxxqWAB+H/AMUv+DlH/giz8JfE194T139trwp4k1bTbmW0vp/hl4A+LfxT8PRzRMysLXxf4D8C654U1WLKnFxo+s6hbE8CY9wDzP8A4io/+CIf/R2mu/8AiPH7RX/zsqAD/iKj/wCCIf8A0dprv/iPH7RX/wA7KgA/4io/+CIf/R2mu/8AiPH7RX/zsqAD/iKj/wCCIf8A0dprv/iPH7RX/wA7KgA/4io/+CIf/R2mu/8AiPH7RX/zsqAP8xH/AIKa/Gj4d/tF/wDBQn9s747/AAi1yTxN8MPi7+0n8XPiF4B8QTaVquhzaz4U8U+LL/VNE1J9H12007WdNa7sp45WstTsbS+t9xjubeGUFFAPho55+uc8e3v25/TnPUATJz27+mef+Bfn/XrQADIPYZx6c8fX/H+VAC5OfpnnjPb/AGvz6dqADJz/APqzj/vr8KAA5/rzj1Hv6fTmgBMnnp79P1+b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ABQAUAFABQAUAFABQAUAFABQAUAFABQAUAf4ov8AwWk/5Sz/APBRrP8A0eT8f/8A1PdU/pn/ABoA/MY9fTnv/wAB75Pt/XvkATg9x/F+H6jr3yfpgcgAUfUdvqcYOP5YwfqTzQAHHJyffkZHPTOfU/8A1+xADj15znqM56Z69fXtj+HNAB+P5/73+POcYzjoOKADjnnuOhHp9evHHOOmckGgA79ecn69W/n3yMcn2AAAY459OMjHX6k/r168cUAf6Gn/AAY7/wDJN/8Agov/ANjr+zJ/6jfxmoA/u/oAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKAP8AFF/4LSf8pZ/+CjX/AGeT8f8A/wBT3VKAPzFJ5J9+/wBU70AGQe3Zsc+uc8Y/LP60AGf129+eAPbn8+DycA0AGeSe+PUdMj2wP1Pr2oAM8/8AAj375+np+GOPvUABP9T1/wBv/PJ/xoAM8Hp1Hf29+e3f8ehoAUfeHrk/zb/PX0oAQHgDscdSP73p1NAH+hr/AMGO/wDyTf8A4KL/APY6/syf+o38Zs0Af3f0AFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFAH+KL/wWj/5S0f8FGucf8Zk/H/r/wBj7qn/AOv9fqAfmOfbHXp+K+3uT+INADefUfxenb8PXk9c9aAF5yeR2z05yB7c5/Cg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BQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFAH/2Q==", +"attach_logo": "logo-2013-color-small.png,data:image/png;base64,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", +"attach_profile": "rushabh.jpeg,data:image/jpeg;base64,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", +"company_abbr": "WN", +"company_name": "Web Notes", +"company_tagline": "Open Source ERP", +"country": "India", +"currency": "INR", +"customer_1": "RIGPL", +"customer_2": "Mahesh Engg", +"customer_contact_1": "Aditya Duggal", +"customer_contact_2": "Mahesh Malani", +"first_name": "Rushabh", +"fy_start": "1st Apr", +"item_1": "Enterprise Plan", +"item_2": "Small Business", +"item_3": "Solo", +"item_4": "Manual", +"item_buy_1": "Server Hosting", +"item_buy_2": "Adwords", +"item_buy_group_1": "Services", +"item_buy_group_2": "Services", +"item_buy_group_3": "Raw Material", +"item_buy_group_4": "Raw Material", +"item_buy_group_5": "Raw Material", +"item_buy_uom_1": "Unit", +"item_buy_uom_2": "Unit", +"item_buy_uom_3": "Unit", +"item_buy_uom_4": "Unit", +"item_buy_uom_5": "Unit", +"item_group_1": "Services", +"item_group_2": "Services", +"item_group_3": "Services", +"item_group_4": "Products", +"item_group_5": "Products", +"item_img_1": "logo-2013-color-small.png,data:image/png;base64,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", +"item_uom_1": "Unit", +"item_uom_2": "Unit", +"item_uom_3": "Unit", +"item_uom_4": "Unit", +"item_uom_5": "Unit", +"last_name": "Mehta", +"supplier_1": "Google", +"supplier_2": "Hetzner", +"supplier_3": "Digital Ocean", +"tax_1": "Service Tax", +"tax_rate_1": "12.5", +"timezone": "Asia/Calcutta", +"password": "password", +"email": "test@erpnext.com", } \ No newline at end of file diff --git a/startup/install.py b/startup/install.py index 59b74965b9e..fd7221380dc 100644 --- a/startup/install.py +++ b/startup/install.py @@ -71,6 +71,7 @@ def import_defaults(): {'doctype': 'Item Group', 'item_group_name': 'Raw Material', 'is_group': 'No', 'parent_item_group': 'All Item Groups'}, {'doctype': 'Item Group', 'item_group_name': 'Services', 'is_group': 'No', 'parent_item_group': 'All Item Groups'}, {'doctype': 'Item Group', 'item_group_name': 'Sub Assemblies', 'is_group': 'No', 'parent_item_group': 'All Item Groups'}, + {'doctype': 'Item Group', 'item_group_name': 'Consumable', 'is_group': 'No', 'parent_item_group': 'All Item Groups'}, # deduction type {'doctype': 'Deduction Type', 'name': 'Income Tax', 'description': 'Income Tax', 'deduction_name': 'Income Tax'}, diff --git a/support/doctype/support_ticket/get_support_mails.py b/support/doctype/support_ticket/get_support_mails.py index 4b61352faef..395052aa27e 100644 --- a/support/doctype/support_ticket/get_support_mails.py +++ b/support/doctype/support_ticket/get_support_mails.py @@ -81,7 +81,7 @@ def add_support_communication(subject, content, sender, docname=None, mail=None) make(content=content, sender=sender, subject = subject, doctype="Support Ticket", name=ticket.doc.name, - date=mail.date if mail else today()) + date=mail.date if mail else today(), sent_or_received="Received") if mail: mail.save_attachments_in_doc(ticket.doc) From 187ea3334fbc94b5116f706a2b297b93238f5161 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A1rbara=20Perretti?= Date: Wed, 9 Oct 2013 14:53:44 -0300 Subject: [PATCH 147/200] Fix translate cart.js --- portal/templates/includes/cart.js | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/portal/templates/includes/cart.js b/portal/templates/includes/cart.js index bd3f56533c5..a894b32e6b6 100644 --- a/portal/templates/includes/cart.js +++ b/portal/templates/includes/cart.js @@ -13,11 +13,11 @@ $(document).ready(function() { $(".progress").remove(); if(r.exc) { if(r.exc.indexOf("WebsitePriceListMissingError")!==-1) { - erpnext.cart.show_error("Oops!", "Price List not configured."); + erpnext.cart.show_error("Oops!", wn._("Price List not configured.")); } else if(r["403"]) { - erpnext.cart.show_error("Hey!", "You need to be logged in to view your cart."); + erpnext.cart.show_error("Hey!", wn._("You need to be logged in to view your cart.")); } else { - erpnext.cart.show_error("Oops!", "Something went wrong."); + erpnext.cart.show_error("Oops!", wn._("Something went wrong.")); } } else { erpnext.cart.set_cart_count(); @@ -78,7 +78,7 @@ $.extend(erpnext.cart, { var no_items = $.map(doclist, function(d) { return d.item_code || null;}).length===0; if(no_items) { - erpnext.cart.show_error("Empty :-(", "Go ahead and add something to your cart."); + erpnext.cart.show_error("Empty :-(", wn._("Go ahead and add something to your cart.")); $("#cart-addresses").toggle(false); return; } @@ -117,7 +117,7 @@ $.extend(erpnext.cart, { }); if(!(addresses && addresses.length)) { - $cart_shipping_address.html('
    Hey! Go ahead and add an address
    '); + $cart_shipping_address.html('
    '+wn._("Hey! Go ahead and add an address")+'
    '); } else { erpnext.cart.render_address($cart_shipping_address, addresses, doclist[0].shipping_address_name); erpnext.cart.render_address($cart_billing_address, addresses, doclist[0].customer_address); @@ -283,7 +283,7 @@ $.extend(erpnext.cart, { $("#cart-error") .empty() - .html(msg || "Something went wrong!") + .html(msg || wn._("Something went wrong!")) .toggle(true); } else { window.location.href = "order?name=" + encodeURIComponent(r.message); From 7798934989493a269070785283de1e22f4ba1baf Mon Sep 17 00:00:00 2001 From: Anand Doshi Date: Thu, 10 Oct 2013 12:03:11 +0530 Subject: [PATCH 148/200] [minor] fixed globals and patch for wsgi migration --- .../p06_fix_sle_against_stock_entry.py | 18 +++++------ patches/october_2013/p04_wsgi_migration.py | 30 +++++++++++++++++++ patches/patch_list.py | 1 + utilities/demo/make_demo.py | 2 +- utilities/demo/make_erpnext_demo.py | 2 +- 5 files changed, 40 insertions(+), 13 deletions(-) create mode 100644 patches/october_2013/p04_wsgi_migration.py diff --git a/patches/august_2013/p06_fix_sle_against_stock_entry.py b/patches/august_2013/p06_fix_sle_against_stock_entry.py index 02588bec6d6..2e6c383ebd6 100644 --- a/patches/august_2013/p06_fix_sle_against_stock_entry.py +++ b/patches/august_2013/p06_fix_sle_against_stock_entry.py @@ -1,10 +1,9 @@ import webnotes -cancelled = [] -uncancelled = [] - def execute(): - global cancelled, uncancelled + cancelled = [] + uncancelled = [] + stock_entries = webnotes.conn.sql("""select * from `tabStock Entry` where docstatus >= 1 and date(modified) >= "2013-08-16" and ifnull(production_order, '') != '' and ifnull(bom_no, '') != '' @@ -17,14 +16,12 @@ def execute(): where voucher_type='Stock Entry' and voucher_no=%s and is_cancelled='No'""", entry.name, as_dict=True) if res: - make_stock_entry_detail(entry, res) + make_stock_entry_detail(entry, res, cancelled, uncancelled) if cancelled or uncancelled: - send_email() + send_email(cancelled, uncancelled) -def make_stock_entry_detail(entry, res): - global cancelled, uncancelled - +def make_stock_entry_detail(entry, res, cancelled, uncancelled): fg_item = webnotes.conn.get_value("Production Order", entry.production_order, "production_item") voucher_detail_entries_map = {} @@ -87,9 +84,8 @@ def make_stock_entry_detail(entry, res): uncancelled.append(se.doc.name) -def send_email(): +def send_email(cancelled, uncancelled): from webnotes.utils.email_lib import sendmail_to_system_managers - global cancelled, uncancelled uncancelled = "we have undone the cancellation of the following Stock Entries through a patch:\n" + \ "\n".join(uncancelled) if uncancelled else "" cancelled = "and cancelled the following Stock Entries:\n" + "\n".join(cancelled) \ diff --git a/patches/october_2013/p04_wsgi_migration.py b/patches/october_2013/p04_wsgi_migration.py new file mode 100644 index 00000000000..ca73516c25a --- /dev/null +++ b/patches/october_2013/p04_wsgi_migration.py @@ -0,0 +1,30 @@ +# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. +# License: GNU General Public License v3. See license.txt + +from __future__ import unicode_literals +import webnotes +import webnotes.utils +import os + +def execute(): + base_path = webnotes.utils.get_base_path() + + # Remove symlinks from public folder: + # - server.py + # - web.py + # - unsupported.html + # - blank.html + # - rss.xml + # - sitemap.xml + for file in ("server.py", "web.py", "unsupported.html", "blank.html", "rss.xml", "sitemap.xml"): + file_path = os.path.join(base_path, "public", file) + if os.path.exists(file_path): + os.remove(file_path) + + # Remove wn-web files + # - js/wn-web.js + # - css/wn-web.css + for file_path in (("js", "wn-web.js"), ("css", "wn-web.css")): + file_path = os.path.join(base_path, "public", *file_path) + if os.path.exists(file_path): + os.remove(file_path) \ No newline at end of file diff --git a/patches/patch_list.py b/patches/patch_list.py index a5693854e5a..92dd52742ca 100644 --- a/patches/patch_list.py +++ b/patches/patch_list.py @@ -224,4 +224,5 @@ patch_list = [ "patches.october_2013.p02_set_communication_status", "patches.october_2013.p03_crm_update_status", "execute:webnotes.delete_doc('DocType', 'Setup Control')", + "patches.october_2013.p04_wsgi_migration", ] \ No newline at end of file diff --git a/utilities/demo/make_demo.py b/utilities/demo/make_demo.py index d335528dfc7..219ce864964 100644 --- a/utilities/demo/make_demo.py +++ b/utilities/demo/make_demo.py @@ -75,7 +75,7 @@ def _simulate(): for i in xrange(runs_for): print current_date.strftime("%Y-%m-%d") - webnotes.utils.current_date = current_date + webnotes.local.current_date = current_date if current_date.weekday() in (5, 6): current_date = webnotes.utils.add_days(current_date, 1) diff --git a/utilities/demo/make_erpnext_demo.py b/utilities/demo/make_erpnext_demo.py index d67fb5ece01..bc25d5e34d3 100644 --- a/utilities/demo/make_erpnext_demo.py +++ b/utilities/demo/make_erpnext_demo.py @@ -6,8 +6,8 @@ import webnotes, os import utilities.demo.make_demo def make_demo_app(site=None): - webnotes.flags.mute_emails = 1 webnotes.init(site=site) + webnotes.flags.mute_emails = 1 utilities.demo.make_demo.make(reset=True, simulate=False) # setup demo user etc so that the site it up faster, while the data loads From 69ad94a795c29e11e1ccce7b7712c247243e373b Mon Sep 17 00:00:00 2001 From: Rushabh Mehta Date: Thu, 10 Oct 2013 15:30:12 +0530 Subject: [PATCH 149/200] [minor] fixes to form layouts --- setup/doctype/uom/uom.txt | 18 +----------------- 1 file changed, 1 insertion(+), 17 deletions(-) diff --git a/setup/doctype/uom/uom.txt b/setup/doctype/uom/uom.txt index 6577f6c0058..51d98067552 100644 --- a/setup/doctype/uom/uom.txt +++ b/setup/doctype/uom/uom.txt @@ -2,7 +2,7 @@ { "creation": "2013-01-10 16:34:24", "docstatus": 0, - "modified": "2013-07-25 16:18:17", + "modified": "2013-10-10 15:06:53", "modified_by": "Administrator", "owner": "Administrator" }, @@ -38,22 +38,6 @@ "doctype": "DocType", "name": "UOM" }, - { - "doctype": "DocField", - "fieldname": "trash_reason", - "fieldtype": "Small Text", - "label": "Trash Reason", - "oldfieldname": "trash_reason", - "oldfieldtype": "Small Text", - "read_only": 1 - }, - { - "doctype": "DocField", - "fieldname": "uom_details", - "fieldtype": "Section Break", - "label": "UOM Details", - "oldfieldtype": "Section Break" - }, { "doctype": "DocField", "fieldname": "uom_name", From b604eddbfd47eea2404e4e20e25ac9665fba7fd7 Mon Sep 17 00:00:00 2001 From: Anand Doshi Date: Thu, 10 Oct 2013 15:43:32 +0530 Subject: [PATCH 150/200] [minor] [fixes] view in website and other fixes --- selling/doctype/sales_order/sales_order.py | 2 +- setup/doctype/item_group/item_group.js | 6 ++++++ setup/page/setup_wizard/setup_wizard.py | 5 ++--- stock/doctype/item/item.js | 16 +++++++++------- stock/doctype/item/item.py | 3 +++ stock/doctype/serial_no/serial_no.py | 4 ++-- utilities/demo/make_erpnext_demo.py | 1 + 7 files changed, 24 insertions(+), 13 deletions(-) diff --git a/selling/doctype/sales_order/sales_order.py b/selling/doctype/sales_order/sales_order.py index d3ac7ad339d..af8ea1ad7a0 100644 --- a/selling/doctype/sales_order/sales_order.py +++ b/selling/doctype/sales_order/sales_order.py @@ -202,7 +202,7 @@ class DocType(SellingController): def check_nextdoc_docstatus(self): # Checks Delivery Note - submit_dn = webnotes.conn.sql("select t1.name from `tabDelivery Note` t1,`tabDelivery Note Item` t2 where t1.name = t2.parent and t2.prevdoc_docname = '%s' and t1.docstatus = 1" % (self.doc.name)) + submit_dn = webnotes.conn.sql("select t1.name from `tabDelivery Note` t1,`tabDelivery Note Item` t2 where t1.name = t2.parent and t2.against_sales_order = %s and t1.docstatus = 1", self.doc.name) if submit_dn: msgprint("Delivery Note : " + cstr(submit_dn[0][0]) + " has been submitted against " + cstr(self.doc.doctype) + ". Please cancel Delivery Note : " + cstr(submit_dn[0][0]) + " first and then cancel "+ cstr(self.doc.doctype), raise_exception = 1) diff --git a/setup/doctype/item_group/item_group.js b/setup/doctype/item_group/item_group.js index 31edef27dec..0c18db001c8 100644 --- a/setup/doctype/item_group/item_group.js +++ b/setup/doctype/item_group/item_group.js @@ -7,6 +7,12 @@ cur_frm.cscript.refresh = function(doc, cdt, cdn) { cur_frm.add_custom_button("Item Group Tree", function() { wn.set_route("Sales Browser", "Item Group"); }) + + if(!doc.__islocal && doc.show_in_website) { + cur_frm.add_custom_button("View In Website", function() { + window.open(doc.page_name); + }, "icon-globe"); + } } cur_frm.cscript.set_root_readonly = function(doc) { diff --git a/setup/page/setup_wizard/setup_wizard.py b/setup/page/setup_wizard/setup_wizard.py index 12767639c84..d506d419542 100644 --- a/setup/page/setup_wizard/setup_wizard.py +++ b/setup/page/setup_wizard/setup_wizard.py @@ -17,9 +17,8 @@ def setup_account(args=None): args = webnotes.local.form_dict if isinstance(args, basestring): args = json.loads(args) - - webnotes.conn.begin() - + args = webnotes._dict(args) + update_profile_name(args) create_fiscal_year_and_company(args) set_defaults(args) diff --git a/stock/doctype/item/item.js b/stock/doctype/item/item.js index a83032e8f26..d0b8492ddd9 100644 --- a/stock/doctype/item/item.js +++ b/stock/doctype/item/item.js @@ -11,14 +11,16 @@ cur_frm.cscript.refresh = function(doc) { && doc.__islocal) cur_frm.toggle_display("item_code", sys_defaults.item_naming_by!="Naming Series" && doc.__islocal) + + if(!doc.__islocal && doc.show_in_website) { + cur_frm.add_custom_button("View In Website", function() { + window.open(doc.page_name); + }, "icon-globe"); + } - - if ((!doc.__islocal) && (doc.is_stock_item == 'Yes')) { - var callback = function(r, rt) { - var enabled = (r.message == 'exists') ? false : true; - cur_frm.toggle_enable(['has_serial_no', 'is_stock_item', 'valuation_method'], enabled); - } - return $c_obj(make_doclist(doc.doctype, doc.name),'check_if_sle_exists','',callback); + if (!doc.__islocal && doc.is_stock_item == 'Yes') { + cur_frm.toggle_enable(['has_serial_no', 'is_stock_item', 'valuation_method'], + doc.__sle_exists=="exists" ? false : true); } } diff --git a/stock/doctype/item/item.py b/stock/doctype/item/item.py index aedb71c2c23..595895f61a7 100644 --- a/stock/doctype/item/item.py +++ b/stock/doctype/item/item.py @@ -14,6 +14,9 @@ from webnotes.model.controller import DocListController class WarehouseNotSet(Exception): pass class DocType(DocListController): + def onload(self): + self.doc.fields["__sle_exists"] = self.check_if_sle_exists() + def autoname(self): if webnotes.conn.get_default("item_naming_by")=="Naming Series": from webnotes.model.doc import make_autoname diff --git a/stock/doctype/serial_no/serial_no.py b/stock/doctype/serial_no/serial_no.py index 1feab02cf57..3b9704fcd57 100644 --- a/stock/doctype/serial_no/serial_no.py +++ b/stock/doctype/serial_no/serial_no.py @@ -14,9 +14,9 @@ class SerialNoCannotCreateDirectError(webnotes.ValidationError): pass class SerialNoCannotCannotChangeError(webnotes.ValidationError): pass class DocType(StockController): - def __init__(self, doc, doclist=[]): + def __init__(self, doc, doclist=None): self.doc = doc - self.doclist = doclist + self.doclist = doclist or [] self.via_stock_ledger = False def validate(self): diff --git a/utilities/demo/make_erpnext_demo.py b/utilities/demo/make_erpnext_demo.py index bc25d5e34d3..262a7595c22 100644 --- a/utilities/demo/make_erpnext_demo.py +++ b/utilities/demo/make_erpnext_demo.py @@ -15,6 +15,7 @@ def make_demo_app(site=None): make_demo_login_page() make_demo_on_login_script() utilities.demo.make_demo.make(reset=False, simulate=True) + webnotes.destroy() def make_demo_user(): from webnotes.auth import _update_password From 373680bbae0895a9af1d6500c63d224cc3347b5a Mon Sep 17 00:00:00 2001 From: Anand Doshi Date: Thu, 10 Oct 2013 16:04:40 +0530 Subject: [PATCH 151/200] Merged master into wsgi --- accounts/doctype/gl_entry/gl_entry.py | 2 +- .../purchase_invoice/purchase_invoice.py | 31 ++- .../doctype/sales_invoice/sales_invoice.py | 2 - .../doctype/sales_invoice/sales_invoice.txt | 3 +- .../item_wise_purchase_register.py | 4 +- .../item_wise_sales_register.py | 14 +- buying/page/buying_home/buying_home.js | 5 + .../__init__.py | 0 .../supplier_addresses_and_contacts.txt | 22 ++ controllers/buying_controller.py | 19 +- controllers/selling_controller.py | 32 +-- hr/doctype/employee/employee.js | 2 +- .../production_order/production_order.py | 29 ++- .../october_2013/p01_fix_serial_no_status.py | 18 ++ ...petual_inventory_stock_transfer_utility.py | 86 +++++++ .../set_stock_value_diff_in_sle.py | 10 + selling/doctype/lead/lead.py | 2 +- selling/doctype/lead/lead.txt | 116 ++++----- selling/doctype/opportunity/opportunity.py | 17 +- selling/doctype/opportunity/opportunity.txt | 16 +- selling/doctype/quotation/quotation.py | 17 +- selling/doctype/sales_order/sales_order.py | 7 +- selling/utils/__init__.py | 2 +- stock/doctype/delivery_note/delivery_note.py | 31 --- .../landed_cost_wizard/landed_cost_wizard.py | 4 +- .../material_request/material_request.py | 12 +- .../purchase_receipt/purchase_receipt.py | 21 +- stock/doctype/serial_no/serial_no.py | 225 ++++++++++++++++-- stock/doctype/stock_entry/stock_entry.py | 24 +- stock/doctype/stock_entry/test_stock_entry.py | 16 +- .../stock_ledger_entry/stock_ledger_entry.py | 138 +---------- stock/utils.py | 7 + .../maintenance_schedules.txt | 4 +- 33 files changed, 520 insertions(+), 418 deletions(-) create mode 100644 buying/report/supplier_addresses_and_contacts/__init__.py create mode 100644 buying/report/supplier_addresses_and_contacts/supplier_addresses_and_contacts.txt create mode 100644 patches/october_2013/p01_fix_serial_no_status.py create mode 100644 patches/october_2013/perpetual_inventory_stock_transfer_utility.py create mode 100644 patches/october_2013/set_stock_value_diff_in_sle.py diff --git a/accounts/doctype/gl_entry/gl_entry.py b/accounts/doctype/gl_entry/gl_entry.py index 22435120e0f..7a73b067565 100644 --- a/accounts/doctype/gl_entry/gl_entry.py +++ b/accounts/doctype/gl_entry/gl_entry.py @@ -107,7 +107,7 @@ class DocType: _(" does not belong to the company") + ": " + self.doc.company) def check_negative_balance(account, adv_adj=False): - if not adv_adj: + if not adv_adj and account: account_details = webnotes.conn.get_value("Account", account, ["allow_negative_balance", "debit_or_credit"], as_dict=True) if not account_details["allow_negative_balance"]: diff --git a/accounts/doctype/purchase_invoice/purchase_invoice.py b/accounts/doctype/purchase_invoice/purchase_invoice.py index 46faf3df599..c79bfd66487 100644 --- a/accounts/doctype/purchase_invoice/purchase_invoice.py +++ b/accounts/doctype/purchase_invoice/purchase_invoice.py @@ -337,7 +337,7 @@ class DocType(BuyingController): ) # tax table gl entries - valuation_tax = 0 + valuation_tax = {} for tax in self.doclist.get({"parentfield": "purchase_tax_details"}): if tax.category in ("Total", "Valuation and Total") and flt(tax.tax_amount): gl_entries.append( @@ -352,8 +352,11 @@ class DocType(BuyingController): ) # accumulate valuation tax - if tax.category in ("Valuation", "Valuation and Total") and flt(tax.tax_amount): - valuation_tax += (tax.add_deduct_tax == "Add" and 1 or -1) * flt(tax.tax_amount) + if tax.category in ("Valuation", "Valuation and Total") and flt(tax.tax_amount) \ + and tax.cost_center: + valuation_tax.setdefault(tax.cost_center, 0) + valuation_tax[tax.cost_center] += \ + (tax.add_deduct_tax == "Add" and 1 or -1) * flt(tax.tax_amount) # item gl entries stock_item_and_auto_accounting_for_stock = False @@ -394,15 +397,19 @@ class DocType(BuyingController): if stock_item_and_auto_accounting_for_stock and valuation_tax: # credit valuation tax amount in "Expenses Included In Valuation" # this will balance out valuation amount included in cost of goods sold - gl_entries.append( - self.get_gl_dict({ - "account": self.get_company_default("expenses_included_in_valuation"), - "cost_center": self.get_company_default("cost_center"), - "against": self.doc.credit_to, - "credit": valuation_tax, - "remarks": self.doc.remarks or "Accounting Entry for Stock" - }) - ) + expenses_included_in_valuation = \ + self.get_company_default("expenses_included_in_valuation") + + for cost_center, amount in valuation_tax.items(): + gl_entries.append( + self.get_gl_dict({ + "account": expenses_included_in_valuation, + "cost_center": cost_center, + "against": self.doc.credit_to, + "credit": amount, + "remarks": self.doc.remarks or "Accounting Entry for Stock" + }) + ) # writeoff account includes petty difference in the invoice amount # and the amount that is paid diff --git a/accounts/doctype/sales_invoice/sales_invoice.py b/accounts/doctype/sales_invoice/sales_invoice.py index 1dca77b3fba..5c7597c4032 100644 --- a/accounts/doctype/sales_invoice/sales_invoice.py +++ b/accounts/doctype/sales_invoice/sales_invoice.py @@ -83,7 +83,6 @@ class DocType(SellingController): def on_submit(self): if cint(self.doc.update_stock) == 1: self.update_stock_ledger() - self.update_serial_nos() else: # Check for Approving Authority if not self.doc.recurring_id: @@ -111,7 +110,6 @@ class DocType(SellingController): def on_cancel(self): if cint(self.doc.update_stock) == 1: self.update_stock_ledger() - self.update_serial_nos(cancel = True) sales_com_obj = get_obj(dt = 'Sales Common') sales_com_obj.check_stop_sales_order(self) diff --git a/accounts/doctype/sales_invoice/sales_invoice.txt b/accounts/doctype/sales_invoice/sales_invoice.txt index 77cf2ccef2b..8cd83c4596e 100644 --- a/accounts/doctype/sales_invoice/sales_invoice.txt +++ b/accounts/doctype/sales_invoice/sales_invoice.txt @@ -2,7 +2,7 @@ { "creation": "2013-05-24 19:29:05", "docstatus": 0, - "modified": "2013-10-02 14:24:50", + "modified": "2013-10-03 18:54:31", "modified_by": "Administrator", "owner": "Administrator" }, @@ -181,7 +181,6 @@ "search_index": 1 }, { - "default": "Today", "description": "Enter the date by which payments from customer is expected against this invoice.", "doctype": "DocField", "fieldname": "due_date", diff --git a/accounts/report/item_wise_purchase_register/item_wise_purchase_register.py b/accounts/report/item_wise_purchase_register/item_wise_purchase_register.py index bd0726e37d9..1c3cef3115d 100644 --- a/accounts/report/item_wise_purchase_register/item_wise_purchase_register.py +++ b/accounts/report/item_wise_purchase_register/item_wise_purchase_register.py @@ -81,12 +81,12 @@ def get_tax_accounts(item_list, columns): if account_head not in tax_accounts: tax_accounts.append(account_head) - invoice = item_tax.setdefault(parent, {}) if item_wise_tax_detail: try: item_wise_tax_detail = json.loads(item_wise_tax_detail) for item, tax_amount in item_wise_tax_detail.items(): - invoice.setdefault(item, {})[account_head] = flt(tax_amount) + item_tax.setdefault(parent, {}).setdefault(item, {})[account_head] = \ + flt(tax_amount[1]) except ValueError: continue diff --git a/accounts/report/item_wise_sales_register/item_wise_sales_register.py b/accounts/report/item_wise_sales_register/item_wise_sales_register.py index 77fb6f25e6d..48bc463f14f 100644 --- a/accounts/report/item_wise_sales_register/item_wise_sales_register.py +++ b/accounts/report/item_wise_sales_register/item_wise_sales_register.py @@ -9,7 +9,7 @@ def execute(filters=None): if not filters: filters = {} columns = get_columns() last_col = len(columns) - + item_list = get_items(filters) item_tax, tax_accounts = get_tax_accounts(item_list, columns) @@ -21,7 +21,7 @@ def execute(filters=None): for tax in tax_accounts: row.append(item_tax.get(d.parent, {}).get(d.item_code, {}).get(tax, 0)) - + total_tax = sum(row[last_col:]) row += [total_tax, d.amount + total_tax] @@ -71,19 +71,19 @@ def get_tax_accounts(item_list, columns): tax_details = webnotes.conn.sql("""select parent, account_head, item_wise_tax_detail from `tabSales Taxes and Charges` where parenttype = 'Sales Invoice' and docstatus = 1 and ifnull(account_head, '') != '' - and parent in (%s)""" % ', '.join(['%s']*len(item_list)), tuple([item.parent for item in item_list])) + and parent in (%s)""" % ', '.join(['%s']*len(item_list)), + tuple([item.parent for item in item_list])) for parent, account_head, item_wise_tax_detail in tax_details: if account_head not in tax_accounts: tax_accounts.append(account_head) - - invoice = item_tax.setdefault(parent, {}) + if item_wise_tax_detail: try: item_wise_tax_detail = json.loads(item_wise_tax_detail) for item, tax_amount in item_wise_tax_detail.items(): - invoice.setdefault(item, {})[account_head] = flt(tax_amount) - + item_tax.setdefault(parent, {}).setdefault(item, {})[account_head] = \ + flt(tax_amount[1]) except ValueError: continue diff --git a/buying/page/buying_home/buying_home.js b/buying/page/buying_home/buying_home.js index 5db57f4f02b..eec0725de97 100644 --- a/buying/page/buying_home/buying_home.js +++ b/buying/page/buying_home/buying_home.js @@ -145,6 +145,11 @@ wn.module_page["Buying"] = [ route: "query-report/Purchase Order Trends", doctype: "Purchase Order" }, + { + "label":wn._("Supplier Addresses And Contacts"), + route: "query-report/Supplier Addresses and Contacts", + doctype: "Supplier" + }, ] } ] diff --git a/buying/report/supplier_addresses_and_contacts/__init__.py b/buying/report/supplier_addresses_and_contacts/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/buying/report/supplier_addresses_and_contacts/supplier_addresses_and_contacts.txt b/buying/report/supplier_addresses_and_contacts/supplier_addresses_and_contacts.txt new file mode 100644 index 00000000000..fac1e9e929c --- /dev/null +++ b/buying/report/supplier_addresses_and_contacts/supplier_addresses_and_contacts.txt @@ -0,0 +1,22 @@ +[ + { + "creation": "2013-10-09 10:38:40", + "docstatus": 0, + "modified": "2013-10-09 10:53:52", + "modified_by": "Administrator", + "owner": "Administrator" + }, + { + "doctype": "Report", + "is_standard": "Yes", + "name": "__common__", + "query": "SELECT\n `tabSupplier`.name as \"Supplier:Link/Supplier:120\",\n\t`tabSupplier`.supplier_name as \"Supplier Name::120\",\n\t`tabSupplier`.supplier_type as \"Supplier Type:Link/Supplier Type:120\",\n\tconcat_ws(', ', \n\t\ttrim(',' from `tabAddress`.address_line1), \n\t\ttrim(',' from tabAddress.address_line2), \n\t\ttabAddress.state, tabAddress.pincode, tabAddress.country\n\t) as 'Address::180',\n concat_ws(', ', `tabContact`.first_name, `tabContact`.last_name) as 'Contact Name::180',\n\t`tabContact`.phone as \"Phone\",\n\t`tabContact`.mobile_no as \"Mobile No\",\n\t`tabContact`.email_id as \"Email Id::120\",\n\t`tabContact`.is_primary_contact as \"Is Primary Contact::120\"\nFROM\n\t`tabSupplier`\n\tleft join `tabAddress` on (\n\t\t`tabAddress`.supplier=`tabSupplier`.name\n\t)\n\tleft join `tabContact` on (\n\t\t`tabContact`.supplier=`tabSupplier`.name\n\t)\nWHERE\n\t`tabSupplier`.docstatus<2\nORDER BY\n\t`tabSupplier`.name asc", + "ref_doctype": "Supplier", + "report_name": "Supplier Addresses and Contacts", + "report_type": "Query Report" + }, + { + "doctype": "Report", + "name": "Supplier Addresses and Contacts" + } +] \ No newline at end of file diff --git a/controllers/buying_controller.py b/controllers/buying_controller.py index 7e49e60f8a1..25d76aa66d6 100644 --- a/controllers/buying_controller.py +++ b/controllers/buying_controller.py @@ -24,7 +24,7 @@ class BuyingController(StockController): self.doc.supplier_name = webnotes.conn.get_value("Supplier", self.doc.supplier, "supplier_name") self.validate_stock_or_nonstock_items() - self.validate_warehouse_belongs_to_company() + self.validate_warehouse() def set_missing_values(self, for_validate=False): super(BuyingController, self).set_missing_values(for_validate) @@ -49,17 +49,20 @@ class BuyingController(StockController): if supplier: self.doc.supplier = supplier break + + def validate_warehouse(self): + from stock.utils import validate_warehouse_user, validate_warehouse_company + + warehouses = list(set([d.warehouse for d in + self.doclist.get({"doctype": self.tname}) if d.warehouse])) + + for w in warehouses: + validate_warehouse_user(w) + validate_warehouse_company(w, self.doc.company) def get_purchase_tax_details(self): self.doclist = self.doc.clear_table(self.doclist, "purchase_tax_details") self.set_taxes("purchase_tax_details", "purchase_other_charges") - - def validate_warehouse_belongs_to_company(self): - for warehouse, company in webnotes.conn.get_values("Warehouse", - self.doclist.get_distinct_values("warehouse"), "company").items(): - if company and company != self.doc.company: - webnotes.msgprint(_("Company mismatch for Warehouse") + (": %s" % (warehouse,)), - raise_exception=WrongWarehouseCompany) def validate_stock_or_nonstock_items(self): if not self.get_stock_items(): diff --git a/controllers/selling_controller.py b/controllers/selling_controller.py index 2816524160e..d78cf932b46 100644 --- a/controllers/selling_controller.py +++ b/controllers/selling_controller.py @@ -236,34 +236,4 @@ class SellingController(StockController): self.doc.order_type = "Sales" elif self.doc.order_type not in valid_types: msgprint(_(self.meta.get_label("order_type")) + " " + - _("must be one of") + ": " + comma_or(valid_types), - raise_exception=True) - - def update_serial_nos(self, cancel=False): - from stock.doctype.stock_ledger_entry.stock_ledger_entry import update_serial_nos_after_submit, get_serial_nos - update_serial_nos_after_submit(self, self.doc.doctype, self.fname) - update_serial_nos_after_submit(self, self.doc.doctype, "packing_details") - - for table_fieldname in (self.fname, "packing_details"): - for d in self.doclist.get({"parentfield": table_fieldname}): - for serial_no in get_serial_nos(d.serial_no): - sr = webnotes.bean("Serial No", serial_no) - if cancel: - sr.doc.status = "Available" - for fieldname in ("warranty_expiry_date", "delivery_document_type", - "delivery_document_no", "delivery_date", "delivery_time", "customer", - "customer_name"): - sr.doc.fields[fieldname] = None - else: - sr.doc.delivery_document_type = self.doc.doctype - sr.doc.delivery_document_no = self.doc.name - sr.doc.delivery_date = self.doc.posting_date - sr.doc.delivery_time = self.doc.posting_time - sr.doc.customer = self.doc.customer - sr.doc.customer_name = self.doc.customer_name - if sr.doc.warranty_period: - sr.doc.warranty_expiry_date = add_days(cstr(self.doc.posting_date), - cint(sr.doc.warranty_period)) - sr.doc.status = 'Delivered' - - sr.save() + _("must be one of") + ": " + comma_or(valid_types), raise_exception=True) diff --git a/hr/doctype/employee/employee.js b/hr/doctype/employee/employee.js index 01200e7d22c..615e2761b8a 100644 --- a/hr/doctype/employee/employee.js +++ b/hr/doctype/employee/employee.js @@ -4,7 +4,6 @@ wn.provide("erpnext.hr"); erpnext.hr.EmployeeController = wn.ui.form.Controller.extend({ setup: function() { - this.setup_leave_approver_select(); this.frm.fields_dict.user_id.get_query = function(doc,cdt,cdn) { return { query:"core.doctype.profile.profile.profile_query"} } this.frm.fields_dict.reports_to.get_query = function(doc,cdt,cdn) { @@ -12,6 +11,7 @@ erpnext.hr.EmployeeController = wn.ui.form.Controller.extend({ }, onload: function() { + this.setup_leave_approver_select(); this.frm.toggle_display(["esic_card_no", "gratuity_lic_id", "pan_number", "pf_number"], wn.control_panel.country==="India"); if(this.frm.doc.__islocal) this.frm.set_value("employee_name", ""); diff --git a/manufacturing/doctype/production_order/production_order.py b/manufacturing/doctype/production_order/production_order.py index a280a822029..6bceca6da8f 100644 --- a/manufacturing/doctype/production_order/production_order.py +++ b/manufacturing/doctype/production_order/production_order.py @@ -21,13 +21,14 @@ class DocType: utilities.validate_status(self.doc.status, ["Draft", "Submitted", "Stopped", "In Process", "Completed", "Cancelled"]) - if self.doc.production_item : - item_detail = webnotes.conn.sql("select name from `tabItem` where name = '%s' and docstatus != 2" - % self.doc.production_item, as_dict = 1) - if not item_detail: - msgprint("Item '%s' does not exist or cancelled in the system." - % cstr(self.doc.production_item), raise_exception=1) - + self.validate_bom_no() + self.validate_sales_order() + self.validate_warehouse() + + from utilities.transaction_base import validate_uom_is_integer + validate_uom_is_integer(self.doclist, "stock_uom", ["qty", "produced_qty"]) + + def validate_bom_no(self): if self.doc.bom_no: bom = webnotes.conn.sql("""select name from `tabBOM` where name=%s and docstatus=1 and is_active=1 and item=%s""" @@ -37,16 +38,20 @@ class DocType: May be BOM not exists or inactive or not submitted or for some other item.""" % cstr(self.doc.bom_no), raise_exception=1) + def validate_sales_order(self): if self.doc.sales_order: if not webnotes.conn.sql("""select name from `tabSales Order` where name=%s and docstatus = 1""", self.doc.sales_order): msgprint("Sales Order: %s is not valid" % self.doc.sales_order, raise_exception=1) - + self.validate_production_order_against_so() - - from utilities.transaction_base import validate_uom_is_integer - validate_uom_is_integer(self.doclist, "stock_uom", ["qty", "produced_qty"]) - + + def validate_warehouse(self): + from stock.utils import validate_warehouse_user, validate_warehouse_company + + for w in [self.doc.fg_warehouse, self.doc.wip_warehouse]: + validate_warehouse_user(w) + validate_warehouse_company(w, self.doc.company) def validate_production_order_against_so(self): # already ordered qty diff --git a/patches/october_2013/p01_fix_serial_no_status.py b/patches/october_2013/p01_fix_serial_no_status.py new file mode 100644 index 00000000000..0bfc400a8e9 --- /dev/null +++ b/patches/october_2013/p01_fix_serial_no_status.py @@ -0,0 +1,18 @@ +# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. +# License: GNU General Public License v3. See license.txt + +from __future__ import unicode_literals +import webnotes +from webnotes.utils import flt + +def execute(): + serial_nos = webnotes.conn.sql("""select name from `tabSerial No` where status!='Not in Use' + and docstatus=0""") + for sr in serial_nos: + sr_bean = webnotes.bean("Serial No", sr[0]) + sr_bean.make_controller().via_stock_ledger = True + sr_bean.run_method("validate") + sr_bean.save() + + webnotes.conn.sql("""update `tabSerial No` set warehouse='' where status in + ('Delivered', 'Purchase Returned')""") \ No newline at end of file diff --git a/patches/october_2013/perpetual_inventory_stock_transfer_utility.py b/patches/october_2013/perpetual_inventory_stock_transfer_utility.py new file mode 100644 index 00000000000..d8cade78eb7 --- /dev/null +++ b/patches/october_2013/perpetual_inventory_stock_transfer_utility.py @@ -0,0 +1,86 @@ +# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. +# License: GNU General Public License v3. See license.txt + +from __future__ import unicode_literals +import webnotes +from webnotes.utils import nowdate, nowtime, cstr +from accounts.utils import get_fiscal_year + +def execute(): + item_map = {} + for item in webnotes.conn.sql("""select * from tabItem""", as_dict=1): + item_map.setdefault(item.name, item) + + warehouse_map = get_warehosue_map() + naming_series = "STE/13/" + + for company in webnotes.conn.sql("select name from tabCompany"): + stock_entry = [{ + "doctype": "Stock Entry", + "naming_series": naming_series, + "posting_date": nowdate(), + "posting_time": nowtime(), + "purpose": "Material Transfer", + "company": company[0], + "remarks": "Material Transfer to activate perpetual inventory", + "fiscal_year": get_fiscal_year(nowdate())[0] + }] + expense_account = "Cost of Goods Sold - NISL" + cost_center = "Default CC Ledger - NISL" + + for bin in webnotes.conn.sql("""select * from tabBin bin where ifnull(item_code, '')!='' + and ifnull(warehouse, '') in (%s) and ifnull(actual_qty, 0) != 0 + and (select company from tabWarehouse where name=bin.warehouse)=%s""" % + (', '.join(['%s']*len(warehouse_map)), '%s'), + (warehouse_map.keys() + [company[0]]), as_dict=1): + item_details = item_map[bin.item_code] + new_warehouse = warehouse_map[bin.warehouse].get("fixed_asset_warehouse") \ + if cstr(item_details.is_asset_item) == "Yes" \ + else warehouse_map[bin.warehouse].get("current_asset_warehouse") + + if item_details.has_serial_no == "Yes": + serial_no = "\n".join([d[0] for d in webnotes.conn.sql("""select name + from `tabSerial No` where item_code = %s and warehouse = %s + and status in ('Available', 'Sales Returned')""", + (bin.item_code, bin.warehouse))]) + else: + serial_no = None + + stock_entry.append({ + "doctype": "Stock Entry Detail", + "parentfield": "mtn_details", + "s_warehouse": bin.warehouse, + "t_warehouse": new_warehouse, + "item_code": bin.item_code, + "description": item_details.description, + "qty": bin.actual_qty, + "transfer_qty": bin.actual_qty, + "uom": item_details.stock_uom, + "stock_uom": item_details.stock_uom, + "conversion_factor": 1, + "expense_account": expense_account, + "cost_center": cost_center, + "serial_no": serial_no + }) + + webnotes.bean(stock_entry).insert() + +def get_warehosue_map(): + return { + "MAHAPE": { + "current_asset_warehouse": "Mahape-New - NISL", + "fixed_asset_warehouse": "" + }, + "DROP SHIPMENT": { + "current_asset_warehouse": "Drop Shipment-New - NISL", + "fixed_asset_warehouse": "" + }, + "TRANSIT": { + "current_asset_warehouse": "Transit-New - NISL", + "fixed_asset_warehouse": "" + }, + "ASSET - MAHAPE": { + "current_asset_warehouse": "", + "fixed_asset_warehouse": "Assets-New - NISL" + } + } \ No newline at end of file diff --git a/patches/october_2013/set_stock_value_diff_in_sle.py b/patches/october_2013/set_stock_value_diff_in_sle.py new file mode 100644 index 00000000000..25f95e0e6da --- /dev/null +++ b/patches/october_2013/set_stock_value_diff_in_sle.py @@ -0,0 +1,10 @@ +# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. +# License: GNU General Public License v3. See license.txt + +from __future__ import unicode_literals +import webnotes +from webnotes.utils import cint + +def execute(): + from patches.september_2012 import repost_stock + repost_stock.execute() \ No newline at end of file diff --git a/selling/doctype/lead/lead.py b/selling/doctype/lead/lead.py index b42a3807582..3cc603fc34f 100644 --- a/selling/doctype/lead/lead.py +++ b/selling/doctype/lead/lead.py @@ -121,4 +121,4 @@ def make_opportunity(source_name, target_doclist=None): } }}, target_doclist) - return [d.fields for d in doclist] \ No newline at end of file + return [d if isinstance(d, dict) else d.fields for d in doclist] diff --git a/selling/doctype/lead/lead.txt b/selling/doctype/lead/lead.txt index 4f481b0a5e4..b700a2e1464 100644 --- a/selling/doctype/lead/lead.txt +++ b/selling/doctype/lead/lead.txt @@ -2,7 +2,7 @@ { "creation": "2013-04-10 11:45:37", "docstatus": 0, - "modified": "2013-10-03 17:24:33", + "modified": "2013-10-09 15:27:54", "modified_by": "Administrator", "owner": "Administrator" }, @@ -159,8 +159,63 @@ "doctype": "DocField", "fieldname": "communication_history", "fieldtype": "Section Break", - "label": "Communication History", - "options": "icon-comments" + "label": "Communication", + "options": "icon-comments", + "print_hide": 1 + }, + { + "default": "__user", + "doctype": "DocField", + "fieldname": "lead_owner", + "fieldtype": "Link", + "in_filter": 1, + "label": "Lead Owner", + "oldfieldname": "lead_owner", + "oldfieldtype": "Link", + "options": "Profile", + "search_index": 1 + }, + { + "doctype": "DocField", + "fieldname": "col_break123", + "fieldtype": "Column Break", + "width": "50%" + }, + { + "allow_on_submit": 0, + "description": "Your sales person who will contact the lead in future", + "doctype": "DocField", + "fieldname": "contact_by", + "fieldtype": "Link", + "hidden": 0, + "in_filter": 1, + "label": "Next Contact By", + "oldfieldname": "contact_by", + "oldfieldtype": "Link", + "options": "Profile", + "print_hide": 0, + "reqd": 0, + "width": "100px" + }, + { + "allow_on_submit": 0, + "description": "Your sales person will get a reminder on this date to contact the lead", + "doctype": "DocField", + "fieldname": "contact_date", + "fieldtype": "Date", + "in_filter": 1, + "label": "Next Contact Date", + "no_copy": 1, + "oldfieldname": "contact_date", + "oldfieldtype": "Date", + "reqd": 0, + "width": "100px" + }, + { + "doctype": "DocField", + "fieldname": "sec_break123", + "fieldtype": "Section Break", + "options": "Simple" }, { "allow_on_submit": 0, @@ -273,18 +328,6 @@ "oldfieldtype": "Select", "options": "\nClient\nChannel Partner\nConsultant" }, - { - "default": "__user", - "doctype": "DocField", - "fieldname": "lead_owner", - "fieldtype": "Link", - "in_filter": 1, - "label": "Lead Owner", - "oldfieldname": "lead_owner", - "oldfieldtype": "Link", - "options": "Profile", - "search_index": 1 - }, { "doctype": "DocField", "fieldname": "market_segment", @@ -334,49 +377,6 @@ "oldfieldtype": "Column Break", "width": "50%" }, - { - "allow_on_submit": 0, - "description": "Your sales person who will contact the lead in future", - "doctype": "DocField", - "fieldname": "contact_by", - "fieldtype": "Link", - "hidden": 0, - "in_filter": 1, - "label": "Next Contact By", - "oldfieldname": "contact_by", - "oldfieldtype": "Link", - "options": "Profile", - "print_hide": 0, - "reqd": 0, - "width": "100px" - }, - { - "allow_on_submit": 0, - "description": "Your sales person will get a reminder on this date to contact the lead", - "doctype": "DocField", - "fieldname": "contact_date", - "fieldtype": "Date", - "in_filter": 1, - "label": "Next Contact Date", - "no_copy": 1, - "oldfieldname": "contact_date", - "oldfieldtype": "Date", - "reqd": 0, - "width": "100px" - }, - { - "depends_on": "eval:!doc.__islocal", - "description": "Date on which the lead was last contacted", - "doctype": "DocField", - "fieldname": "last_contact_date", - "fieldtype": "Date", - "label": "Last Contact Date", - "no_copy": 1, - "oldfieldname": "last_contact_date", - "oldfieldtype": "Date", - "print_hide": 1, - "read_only": 1 - }, { "doctype": "DocField", "fieldname": "company", diff --git a/selling/doctype/opportunity/opportunity.py b/selling/doctype/opportunity/opportunity.py index e63ce6b0607..37672f2afb2 100644 --- a/selling/doctype/opportunity/opportunity.py +++ b/selling/doctype/opportunity/opportunity.py @@ -4,7 +4,7 @@ from __future__ import unicode_literals import webnotes -from webnotes.utils import cstr, getdate, cint +from webnotes.utils import cstr, cint from webnotes.model.bean import getlist from webnotes import msgprint, _ @@ -17,7 +17,7 @@ class DocType(TransactionBase): self.doclist = doclist self.fname = 'enq_details' self.tname = 'Opportunity Item' - + self._prev = webnotes._dict({ "contact_date": webnotes.conn.get_value("Opportunity", self.doc.name, "contact_date") if \ (not cint(self.doc.fields.get("__islocal"))) else None, @@ -70,10 +70,6 @@ class DocType(TransactionBase): def on_update(self): - # Add to calendar - if self.doc.contact_date and self.doc.contact_date_ref != self.doc.contact_date: - webnotes.conn.set(self.doc, 'contact_date_ref',self.doc.contact_date) - self.add_calendar_event() def add_calendar_event(self, opts=None, force=False): @@ -101,14 +97,6 @@ class DocType(TransactionBase): super(DocType, self).add_calendar_event(opts, force) - def set_last_contact_date(self): - if self.doc.contact_date_ref and self.doc.contact_date_ref != self.doc.contact_date: - if getdate(self.doc.contact_date_ref) < getdate(self.doc.contact_date): - self.doc.last_contact_date=self.doc.contact_date_ref - else: - msgprint("Contact Date Cannot be before Last Contact Date") - raise Exception - def validate_item_details(self): if not getlist(self.doclist, 'enquiry_details'): msgprint("Please select items for which enquiry needs to be made") @@ -122,7 +110,6 @@ class DocType(TransactionBase): def validate(self): self.set_status() - self.set_last_contact_date() self.validate_item_details() self.validate_uom_is_integer("uom", "qty") self.validate_lead_cust() diff --git a/selling/doctype/opportunity/opportunity.txt b/selling/doctype/opportunity/opportunity.txt index 02caea0a6d1..3c860ade845 100644 --- a/selling/doctype/opportunity/opportunity.txt +++ b/selling/doctype/opportunity/opportunity.txt @@ -2,7 +2,7 @@ { "creation": "2013-03-07 18:50:30", "docstatus": 0, - "modified": "2013-10-03 16:30:58", + "modified": "2013-10-09 15:26:29", "modified_by": "Administrator", "owner": "Administrator" }, @@ -404,20 +404,6 @@ "oldfieldtype": "Date", "read_only": 0 }, - { - "allow_on_submit": 0, - "depends_on": "eval:!doc.__islocal", - "description": "Date on which the lead was last contacted", - "doctype": "DocField", - "fieldname": "last_contact_date", - "fieldtype": "Date", - "label": "Last Contact Date", - "no_copy": 1, - "oldfieldname": "last_contact_date", - "oldfieldtype": "Date", - "print_hide": 1, - "read_only": 1 - }, { "doctype": "DocField", "fieldname": "to_discuss", diff --git a/selling/doctype/quotation/quotation.py b/selling/doctype/quotation/quotation.py index 697f805a2c0..b6bc45d772a 100644 --- a/selling/doctype/quotation/quotation.py +++ b/selling/doctype/quotation/quotation.py @@ -4,7 +4,7 @@ from __future__ import unicode_literals import webnotes -from webnotes.utils import cstr, getdate +from webnotes.utils import cstr from webnotes.model.bean import getlist from webnotes.model.code import get_obj from webnotes import _, msgprint @@ -97,24 +97,9 @@ class DocType(SellingController): msgprint("You can not select non sales item "+d.item_code+" in Sales Quotation") raise Exception - #--------------Validation For Last Contact Date----------------- - # ==================================================================================================================== - def set_last_contact_date(self): - #if not self.doc.contact_date_ref: - #self.doc.contact_date_ref=self.doc.contact_date - #self.doc.last_contact_date=self.doc.contact_date_ref - if self.doc.contact_date_ref and self.doc.contact_date_ref != self.doc.contact_date: - if getdate(self.doc.contact_date_ref) < getdate(self.doc.contact_date): - self.doc.last_contact_date=self.doc.contact_date_ref - else: - msgprint("Contact Date Cannot be before Last Contact Date") - raise Exception - def validate(self): super(DocType, self).validate() - self.set_status() - self.set_last_contact_date() self.validate_order_type() self.validate_for_items() diff --git a/selling/doctype/sales_order/sales_order.py b/selling/doctype/sales_order/sales_order.py index af8ea1ad7a0..0cdca58ce9b 100644 --- a/selling/doctype/sales_order/sales_order.py +++ b/selling/doctype/sales_order/sales_order.py @@ -126,7 +126,7 @@ class DocType(SellingController): self.validate_po() self.validate_uom_is_integer("stock_uom", "qty") self.validate_for_items() - self.validate_warehouse_user() + self.validate_warehouse() sales_com_obj = get_obj(dt = 'Sales Common') sales_com_obj.check_active_sales_items(self) sales_com_obj.check_conversion_rate(self) @@ -147,14 +147,15 @@ class DocType(SellingController): if not self.doc.delivery_status: self.doc.delivery_status = 'Not Delivered' - def validate_warehouse_user(self): - from stock.utils import validate_warehouse_user + def validate_warehouse(self): + from stock.utils import validate_warehouse_user, validate_warehouse_company warehouses = list(set([d.reserved_warehouse for d in self.doclist.get({"doctype": self.tname}) if d.reserved_warehouse])) for w in warehouses: validate_warehouse_user(w) + validate_warehouse_company(w, self.doc.company) def validate_with_previous_doc(self): super(DocType, self).validate_with_previous_doc(self.tname, { diff --git a/selling/utils/__init__.py b/selling/utils/__init__.py index 801d82bf40e..6e74ac48695 100644 --- a/selling/utils/__init__.py +++ b/selling/utils/__init__.py @@ -74,7 +74,7 @@ def get_item_details(args): out.update(apply_pos_settings(pos_settings, out)) if args.doctype in ("Sales Invoice", "Delivery Note"): - if item_bean.doc.has_serial_no and not args.serial_no: + if item_bean.doc.has_serial_no == "Yes" and not args.serial_no: out.serial_no = _get_serial_nos_by_fifo(args, item_bean) return out diff --git a/stock/doctype/delivery_note/delivery_note.py b/stock/doctype/delivery_note/delivery_note.py index b27d0345ea4..b20e790af76 100644 --- a/stock/doctype/delivery_note/delivery_note.py +++ b/stock/doctype/delivery_note/delivery_note.py @@ -186,7 +186,6 @@ class DocType(SellingController): # create stock ledger entry self.update_stock_ledger() - self.update_serial_nos() self.credit_limit() @@ -204,42 +203,12 @@ class DocType(SellingController): self.update_prevdoc_status() self.update_stock_ledger() - self.update_serial_nos(cancel=True) webnotes.conn.set(self.doc, 'status', 'Cancelled') self.cancel_packing_slips() self.make_cancel_gl_entries() - def update_serial_nos(self, cancel=False): - from stock.doctype.stock_ledger_entry.stock_ledger_entry import update_serial_nos_after_submit, get_serial_nos - update_serial_nos_after_submit(self, "Delivery Note", "delivery_note_details") - update_serial_nos_after_submit(self, "Delivery Note", "packing_details") - - for table_fieldname in ("delivery_note_details", "packing_details"): - for d in self.doclist.get({"parentfield": table_fieldname}): - for serial_no in get_serial_nos(d.serial_no): - sr = webnotes.bean("Serial No", serial_no) - if cancel: - sr.doc.status = "Available" - for fieldname in ("warranty_expiry_date", "delivery_document_type", - "delivery_document_no", "delivery_date", "delivery_time", "customer", - "customer_name"): - sr.doc.fields[fieldname] = None - else: - sr.doc.delivery_document_type = "Delivery Note" - sr.doc.delivery_document_no = self.doc.name - sr.doc.delivery_date = self.doc.posting_date - sr.doc.delivery_time = self.doc.posting_time - sr.doc.customer = self.doc.customer - sr.doc.customer_name = self.doc.customer_name - if sr.doc.warranty_period: - sr.doc.warranty_expiry_date = add_days(cstr(self.doc.posting_date), - cint(sr.doc.warranty_period)) - sr.doc.status = 'Delivered' - - sr.save() - def validate_packed_qty(self): """ Validate that if packed qty exists, it should be equal to qty diff --git a/stock/doctype/landed_cost_wizard/landed_cost_wizard.py b/stock/doctype/landed_cost_wizard/landed_cost_wizard.py index f431537c6c5..89a3b81d572 100644 --- a/stock/doctype/landed_cost_wizard/landed_cost_wizard.py +++ b/stock/doctype/landed_cost_wizard/landed_cost_wizard.py @@ -85,7 +85,6 @@ class DocType: pr_bean = webnotes.bean("Purchase Receipt", pr) pr_bean.run_method("update_ordered_qty", is_cancelled="Yes") - pr_bean.run_method("update_serial_nos", cancel=True) webnotes.conn.sql("""delete from `tabStock Ledger Entry` where voucher_type='Purchase Receipt' and voucher_no=%s""", pr) @@ -97,5 +96,4 @@ class DocType: pr_bean = webnotes.bean("Purchase Receipt", pr) pr_bean.run_method("update_ordered_qty") pr_bean.run_method("update_stock") - pr_bean.run_method("update_serial_nos") - pr_bean.run_method("make_gl_entries") + pr_bean.run_method("make_gl_entries") \ No newline at end of file diff --git a/stock/doctype/material_request/material_request.py b/stock/doctype/material_request/material_request.py index 249062f29d1..d1672ba12c1 100644 --- a/stock/doctype/material_request/material_request.py +++ b/stock/doctype/material_request/material_request.py @@ -68,22 +68,14 @@ class DocType(BuyingController): self.doc.status = "Draft" import utilities - utilities.validate_status(self.doc.status, ["Draft", "Submitted", "Stopped", - "Cancelled"]) + utilities.validate_status(self.doc.status, ["Draft", "Submitted", "Stopped", "Cancelled"]) - # restrict material request type self.validate_value("material_request_type", "in", ["Purchase", "Transfer"]) - # Get Purchase Common Obj pc_obj = get_obj(dt='Purchase Common') - - - # Validate for items pc_obj.validate_for_items(self) - - # Validate qty against SO - self.validate_qty_against_so() + self.validate_qty_against_so() def update_bin(self, is_submit, is_stopped): """ Update Quantity Requested for Purchase in Bin for Material Request of type 'Purchase'""" diff --git a/stock/doctype/purchase_receipt/purchase_receipt.py b/stock/doctype/purchase_receipt/purchase_receipt.py index 7d663b87786..6169b1d9166 100644 --- a/stock/doctype/purchase_receipt/purchase_receipt.py +++ b/stock/doctype/purchase_receipt/purchase_receipt.py @@ -246,26 +246,12 @@ class DocType(BuyingController): self.update_stock() - self.update_serial_nos() + from stock.doctype.serial_no.serial_no import update_serial_nos_after_submit + update_serial_nos_after_submit(self, "Purchase Receipt", "purchase_receipt_details") purchase_controller.update_last_purchase_rate(self, 1) self.make_gl_entries() - - def update_serial_nos(self, cancel=False): - from stock.doctype.stock_ledger_entry.stock_ledger_entry import update_serial_nos_after_submit, get_serial_nos - update_serial_nos_after_submit(self, "Purchase Receipt", "purchase_receipt_details") - - for d in self.doclist.get({"parentfield": "purchase_receipt_details"}): - for serial_no in get_serial_nos(d.serial_no): - sr = webnotes.bean("Serial No", serial_no) - if cancel: - sr.doc.supplier = None - sr.doc.supplier_name = None - else: - sr.doc.supplier = self.doc.supplier - sr.doc.supplier_name = self.doc.supplier_name - sr.save() def check_next_docstatus(self): submit_rv = webnotes.conn.sql("select t1.name from `tabPurchase Invoice` t1,`tabPurchase Invoice Item` t2 where t1.name = t2.parent and t2.purchase_receipt = '%s' and t1.docstatus = 1" % (self.doc.name)) @@ -292,7 +278,6 @@ class DocType(BuyingController): self.update_ordered_qty() self.update_stock() - self.update_serial_nos(cancel=True) self.update_prevdoc_status() pc_obj.update_last_purchase_rate(self, 0) @@ -308,7 +293,7 @@ class DocType(BuyingController): def get_rate(self,arg): return get_obj('Purchase Common').get_rate(arg,self) - + def get_gl_entries_for_stock(self, warehouse_account=None): against_stock_account = self.get_company_default("stock_received_but_not_billed") diff --git a/stock/doctype/serial_no/serial_no.py b/stock/doctype/serial_no/serial_no.py index 3b9704fcd57..93836d64e48 100644 --- a/stock/doctype/serial_no/serial_no.py +++ b/stock/doctype/serial_no/serial_no.py @@ -4,14 +4,22 @@ from __future__ import unicode_literals import webnotes -from webnotes.utils import cint, getdate, nowdate +from webnotes.utils import cint, getdate, nowdate, cstr, flt, add_days import datetime -from webnotes import msgprint, _ +from webnotes import msgprint, _, ValidationError from controllers.stock_controller import StockController -class SerialNoCannotCreateDirectError(webnotes.ValidationError): pass -class SerialNoCannotCannotChangeError(webnotes.ValidationError): pass +class SerialNoCannotCreateDirectError(ValidationError): pass +class SerialNoCannotCannotChangeError(ValidationError): pass +class SerialNoNotRequiredError(ValidationError): pass +class SerialNoRequiredError(ValidationError): pass +class SerialNoQtyError(ValidationError): pass +class SerialNoItemError(ValidationError): pass +class SerialNoWarehouseError(ValidationError): pass +class SerialNoStatusError(ValidationError): pass +class SerialNoNotExistsError(ValidationError): pass +class SerialNoDuplicateError(ValidationError): pass class DocType(StockController): def __init__(self, doc, doclist=None): @@ -21,13 +29,18 @@ class DocType(StockController): def validate(self): if self.doc.fields.get("__islocal") and self.doc.warehouse: - webnotes.throw(_("New Serial No cannot have Warehouse. Warehouse must be set by Stock Entry or Purchase Receipt"), - SerialNoCannotCreateDirectError) + webnotes.throw(_("New Serial No cannot have Warehouse. Warehouse must be \ + set by Stock Entry or Purchase Receipt"), SerialNoCannotCreateDirectError) self.validate_warranty_status() self.validate_amc_status() self.validate_warehouse() self.validate_item() + + if self.via_stock_ledger: + self.set_status() + self.set_purchase_details() + self.set_sales_details() def validate_amc_status(self): """ @@ -41,7 +54,8 @@ class DocType(StockController): validate warranty status """ if (self.doc.maintenance_status == 'Out of Warranty' and self.doc.warranty_expiry_date and getdate(self.doc.warranty_expiry_date) >= datetime.date.today()) or (self.doc.maintenance_status == 'Under Warranty' and (not self.doc.warranty_expiry_date or getdate(self.doc.warranty_expiry_date) < datetime.date.today())): - msgprint("Warranty expiry date and maintenance status mismatch. Please verify", raise_exception=1) + msgprint("Warranty expiry date and maintenance status mismatch. Please verify", + raise_exception=1) def validate_warehouse(self): @@ -49,10 +63,11 @@ class DocType(StockController): item_code, warehouse = webnotes.conn.get_value("Serial No", self.doc.name, ["item_code", "warehouse"]) if item_code != self.doc.item_code: - webnotes.throw(_("Item Code cannot be changed for Serial No."), SerialNoCannotCannotChangeError) + webnotes.throw(_("Item Code cannot be changed for Serial No."), + SerialNoCannotCannotChangeError) if not self.via_stock_ledger and warehouse != self.doc.warehouse: - webnotes.throw(_("Warehouse cannot be changed for Serial No."), SerialNoCannotCannotChangeError) - + webnotes.throw(_("Warehouse cannot be changed for Serial No."), + SerialNoCannotCannotChangeError) def validate_item(self): """ @@ -67,16 +82,89 @@ class DocType(StockController): self.doc.item_name = item.item_name self.doc.brand = item.brand self.doc.warranty_period = item.warranty_period - + + def set_status(self): + last_sle = webnotes.conn.sql("""select * from `tabStock Ledger Entry` + where (serial_no like %s or serial_no like %s or serial_no=%s) + and item_code=%s and ifnull(is_cancelled, 'No')='No' + order by name desc limit 1""", + ("%%%s%%" % (self.doc.name+"\n"), "%%%s%%" % ("\n"+self.doc.name), self.doc.name, + self.doc.item_code), as_dict=1) + + if last_sle: + if last_sle[0].voucher_type == "Stock Entry": + document_type = webnotes.conn.get_value("Stock Entry", last_sle[0].voucher_no, + "purpose") + else: + document_type = last_sle[0].voucher_type + + if last_sle[0].actual_qty > 0: + if document_type == "Sales Return": + self.doc.status = "Sales Returned" + else: + self.doc.status = "Available" + else: + if document_type == "Purchase Return": + self.doc.status = "Purchase Returned" + elif last_sle[0].voucher_type in ("Delivery Note", "Sales Invoice"): + self.doc.status = "Delivered" + else: + self.doc.status = "Not Available" + + def set_purchase_details(self): + purchase_sle = webnotes.conn.sql("""select * from `tabStock Ledger Entry` + where (serial_no like %s or serial_no like %s or serial_no=%s) + and item_code=%s and actual_qty > 0 + and ifnull(is_cancelled, 'No')='No' order by name asc limit 1""", + ("%%%s%%" % (self.doc.name+"\n"), "%%%s%%" % ("\n"+self.doc.name), self.doc.name, + self.doc.item_code), as_dict=1) + + if purchase_sle: + self.doc.purchase_document_type = purchase_sle[0].voucher_type + self.doc.purchase_document_no = purchase_sle[0].voucher_no + self.doc.purchase_date = purchase_sle[0].posting_date + self.doc.purchase_time = purchase_sle[0].posting_time + self.doc.purchase_rate = purchase_sle[0].incoming_rate + if purchase_sle[0].voucher_type == "Purchase Receipt": + self.doc.supplier, self.doc.supplier_name = \ + webnotes.conn.get_value("Purchase Receipt", purchase_sle[0].voucher_no, + ["supplier", "supplier_name"]) + else: + for fieldname in ("purchase_document_type", "purchase_document_no", + "purchase_date", "purchase_time", "purchase_rate", "supplier", "supplier_name"): + self.doc.fields[fieldname] = None + + def set_sales_details(self): + delivery_sle = webnotes.conn.sql("""select * from `tabStock Ledger Entry` + where (serial_no like %s or serial_no like %s or serial_no=%s) + and item_code=%s and actual_qty<0 + and voucher_type in ('Delivery Note', 'Sales Invoice') + and ifnull(is_cancelled, 'No')='No' order by name desc limit 1""", + ("%%%s%%" % (self.doc.name+"\n"), "%%%s%%" % ("\n"+self.doc.name), self.doc.name, + self.doc.item_code), as_dict=1) + if delivery_sle: + self.doc.delivery_document_type = delivery_sle[0].voucher_type + self.doc.delivery_document_no = delivery_sle[0].voucher_no + self.doc.delivery_date = delivery_sle[0].posting_date + self.doc.delivery_time = delivery_sle[0].posting_time + self.doc.customer, self.doc.customer_name = \ + webnotes.conn.get_value(delivery_sle[0].voucher_type, delivery_sle[0].voucher_no, + ["customer", "customer_name"]) + if self.doc.warranty_period: + self.doc.warranty_expiry_date = add_days(cstr(delivery_sle[0].posting_date), + cint(self.doc.warranty_period)) + else: + for fieldname in ("delivery_document_type", "delivery_document_no", + "delivery_date", "delivery_time", "customer", "customer_name", + "warranty_expiry_date"): + self.doc.fields[fieldname] = None + def on_trash(self): if self.doc.status == 'Delivered': - msgprint("Cannot trash Serial No : %s as it is already Delivered" % (self.doc.name), raise_exception = 1) + webnotes.throw(_("Delivered Serial No ") + self.doc.name + _(" can not be deleted")) if self.doc.warehouse: - webnotes.throw(_("Cannot delete Serial No in warehouse. First remove from warehouse, then delete.") + \ - ": " + self.doc.name) - - def on_cancel(self): - self.on_trash() + webnotes.throw(_("Cannot delete Serial No in warehouse. \ + First remove from warehouse, then delete.") + ": " + self.doc.name) def on_rename(self, new, old, merge=False): """rename serial_no text fields""" @@ -93,3 +181,106 @@ class DocType(StockController): webnotes.conn.sql("""update `tab%s` set serial_no = %s where name=%s""" % (dt[0], '%s', '%s'), ('\n'.join(serial_nos), item[0])) + +def process_serial_no(sle): + item_det = get_item_details(sle.item_code) + validate_serial_no(sle, item_det) + update_serial_nos(sle, item_det) + +def validate_serial_no(sle, item_det): + if item_det.has_serial_no=="No": + if sle.serial_no: + webnotes.throw(_("Serial Number should be blank for Non Serialized Item" + ": " + + sle.item_code), SerialNoNotRequiredError) + else: + if sle.serial_no: + serial_nos = get_serial_nos(sle.serial_no) + if cint(sle.actual_qty) != flt(sle.actual_qty): + webnotes.throw(_("Serial No qty cannot be a fraction") + \ + (": %s (%s)" % (sle.item_code, sle.actual_qty))) + if len(serial_nos) and len(serial_nos) != abs(cint(sle.actual_qty)): + webnotes.throw(_("Serial Nos do not match with qty") + \ + (": %s (%s)" % (sle.item_code, sle.actual_qty)), SerialNoQtyError) + + for serial_no in serial_nos: + if webnotes.conn.exists("Serial No", serial_no): + sr = webnotes.bean("Serial No", serial_no) + + if sr.doc.item_code!=sle.item_code: + webnotes.throw(_("Serial No does not belong to Item") + + (": %s (%s)" % (sle.item_code, serial_no)), SerialNoItemError) + + if sr.doc.warehouse and sle.actual_qty > 0: + webnotes.throw(_("Same Serial No") + ": " + sr.doc.name + + _(" can not be received twice"), SerialNoDuplicateError) + + if sle.actual_qty < 0: + if sr.doc.warehouse!=sle.warehouse: + webnotes.throw(_("Serial No") + ": " + serial_no + + _(" does not belong to Warehouse") + ": " + sle.warehouse, + SerialNoWarehouseError) + + if sle.voucher_type in ("Delivery Note", "Sales Invoice") \ + and sr.doc.status != "Available": + webnotes.throw(_("Serial No status must be 'Available' to Deliver") + + ": " + serial_no, SerialNoStatusError) + elif sle.actual_qty < 0: + # transfer out + webnotes.throw(_("Serial No must exist to transfer out.") + \ + ": " + serial_no, SerialNoNotExistsError) + elif not item_det.serial_no_series: + webnotes.throw(_("Serial Number Required for Serialized Item" + ": " + + sle.item_code), SerialNoRequiredError) + +def update_serial_nos(sle, item_det): + if sle.serial_no: + serial_nos = get_serial_nos(sle.serial_no) + for serial_no in serial_nos: + if webnotes.conn.exists("Serial No", serial_no): + sr = webnotes.bean("Serial No", serial_no) + sr.make_controller().via_stock_ledger = True + sr.doc.warehouse = sle.warehouse if sle.actual_qty > 0 else None + sr.save() + elif sle.actual_qty > 0: + make_serial_no(serial_no, sle) + elif sle.actual_qty > 0 and item_det.serial_no_series: + from webnotes.model.doc import make_autoname + serial_nos = [] + for i in xrange(cint(sle.actual_qty)): + serial_nos.append(make_serial_no(make_autoname(item_det.serial_no_series), sle)) + sle.serial_no = "\n".join(serial_nos) + +def get_item_details(item_code): + return webnotes.conn.sql("""select name, has_batch_no, docstatus, + is_stock_item, has_serial_no, serial_no_series + from tabItem where name=%s""", item_code, as_dict=True)[0] + +def get_serial_nos(serial_no): + return [s.strip() for s in cstr(serial_no).strip().replace(',', '\n').split('\n') if s.strip()] + +def make_serial_no(serial_no, sle): + sr = webnotes.new_bean("Serial No") + sr.doc.serial_no = serial_no + sr.doc.item_code = sle.item_code + sr.make_controller().via_stock_ledger = True + sr.insert() + sr.doc.warehouse = sle.warehouse + sr.doc.status = "Available" + sr.save() + webnotes.msgprint(_("Serial No created") + ": " + sr.doc.name) + return sr.doc.name + +def update_serial_nos_after_submit(controller, parenttype, parentfield): + if not hasattr(webnotes, "new_stock_ledger_entries"): + return + + for d in controller.doclist.get({"parentfield": parentfield}): + serial_no = None + for sle in webnotes.new_stock_ledger_entries: + if sle.voucher_detail_no==d.name: + serial_no = sle.serial_no + break + + if d.serial_no != serial_no: + d.serial_no = serial_no + webnotes.conn.set_value(d.doctype, d.name, "serial_no", serial_no) diff --git a/stock/doctype/stock_entry/stock_entry.py b/stock/doctype/stock_entry/stock_entry.py index 535d4c82330..0117864a1be 100644 --- a/stock/doctype/stock_entry/stock_entry.py +++ b/stock/doctype/stock_entry/stock_entry.py @@ -51,13 +51,15 @@ class DocType(StockController): def on_submit(self): self.update_stock_ledger() - self.update_serial_no(1) + + from stock.doctype.serial_no.serial_no import update_serial_nos_after_submit + update_serial_nos_after_submit(self, "Stock Entry", "mtn_details") + self.update_production_order(1) self.make_gl_entries() def on_cancel(self): self.update_stock_ledger() - self.update_serial_no(0) self.update_production_order(0) self.make_cancel_gl_entries() @@ -293,24 +295,6 @@ class DocType(StockController): from `tabStock Entry Detail` where parent in ( select name from `tabStock Entry` where `%s`=%s and docstatus=1) group by item_code""" % (ref_fieldname, "%s"), (self.doc.fields.get(ref_fieldname),))) - - def update_serial_no(self, is_submit): - """Create / Update Serial No""" - - from stock.doctype.stock_ledger_entry.stock_ledger_entry import update_serial_nos_after_submit, get_serial_nos - update_serial_nos_after_submit(self, "Stock Entry", "mtn_details") - - for d in getlist(self.doclist, 'mtn_details'): - for serial_no in get_serial_nos(d.serial_no): - if self.doc.purpose == 'Purchase Return': - sr = webnotes.bean("Serial No", serial_no) - sr.doc.status = "Purchase Returned" if is_submit else "Available" - sr.save() - - if self.doc.purpose == "Sales Return": - sr = webnotes.bean("Serial No", serial_no) - sr.doc.status = "Sales Returned" if is_submit else "Delivered" - sr.save() def update_stock_ledger(self): sl_entries = [] diff --git a/stock/doctype/stock_entry/test_stock_entry.py b/stock/doctype/stock_entry/test_stock_entry.py index e2358eba4f0..b41a6269ad9 100644 --- a/stock/doctype/stock_entry/test_stock_entry.py +++ b/stock/doctype/stock_entry/test_stock_entry.py @@ -7,7 +7,7 @@ from __future__ import unicode_literals import webnotes, unittest from webnotes.utils import flt -from stock.doctype.stock_ledger_entry.stock_ledger_entry import * +from stock.doctype.serial_no.serial_no import * from stock.doctype.purchase_receipt.test_purchase_receipt import set_perpetual_inventory @@ -48,7 +48,7 @@ class TestStockEntry(unittest.TestCase): webnotes.bean("Profile", "test2@example.com").get_controller()\ .add_roles("Sales User", "Sales Manager", "Material User", "Material Manager") - from stock.doctype.stock_ledger_entry.stock_ledger_entry import InvalidWarehouseCompany + from stock.utils import InvalidWarehouseCompany st1 = webnotes.bean(copy=test_records[0]) st1.doclist[1].t_warehouse="_Test Warehouse 2 - _TC1" st1.insert() @@ -721,6 +721,18 @@ class TestStockEntry(unittest.TestCase): se.insert() self.assertRaises(SerialNoNotExistsError, se.submit) + def test_serial_duplicate(self): + self._clear_stock_account_balance() + self.test_serial_by_series() + + se = webnotes.bean(copy=test_records[0]) + se.doclist[1].item_code = "_Test Serialized Item With Series" + se.doclist[1].qty = 1 + se.doclist[1].serial_no = "ABCD00001" + se.doclist[1].transfer_qty = 1 + se.insert() + self.assertRaises(SerialNoDuplicateError, se.submit) + def test_serial_by_series(self): self._clear_stock_account_balance() se = make_serialized_item() diff --git a/stock/doctype/stock_ledger_entry/stock_ledger_entry.py b/stock/doctype/stock_ledger_entry/stock_ledger_entry.py index 1c3d3e132dd..8fef889f724 100644 --- a/stock/doctype/stock_ledger_entry/stock_ledger_entry.py +++ b/stock/doctype/stock_ledger_entry/stock_ledger_entry.py @@ -3,29 +3,17 @@ from __future__ import unicode_literals import webnotes -from webnotes import _, msgprint, ValidationError +from webnotes import _, msgprint from webnotes.utils import cint, flt, getdate, cstr from webnotes.model.controller import DocListController -class InvalidWarehouseCompany(ValidationError): pass -class SerialNoNotRequiredError(ValidationError): pass -class SerialNoRequiredError(ValidationError): pass -class SerialNoQtyError(ValidationError): pass -class SerialNoItemError(ValidationError): pass -class SerialNoWarehouseError(ValidationError): pass -class SerialNoStatusError(ValidationError): pass -class SerialNoNotExistsError(ValidationError): pass - -def get_serial_nos(serial_no): - return [s.strip() for s in cstr(serial_no).strip().replace(',', '\n').split('\n') if s.strip()] - class DocType(DocListController): def __init__(self, doc, doclist=[]): self.doc = doc self.doclist = doclist def validate(self): - from stock.utils import validate_warehouse_user + from stock.utils import validate_warehouse_user, validate_warehouse_company if not hasattr(webnotes, "new_stock_ledger_entries"): webnotes.new_stock_ledger_entries = [] @@ -33,7 +21,7 @@ class DocType(DocListController): self.validate_mandatory() self.validate_item() validate_warehouse_user(self.doc.warehouse) - self.validate_warehouse_company() + validate_warehouse_company(self.doc.warehouse, self.doc.company) self.scrub_posting_time() from accounts.utils import validate_fiscal_year @@ -42,7 +30,9 @@ class DocType(DocListController): def on_submit(self): self.check_stock_frozen_date() self.actual_amt_check() - self.validate_serial_no() + + from stock.doctype.serial_no.serial_no import process_serial_no + process_serial_no(self.doc) #check for item quantity available in stock def actual_amt_check(self): @@ -63,13 +53,6 @@ class DocType(DocListController): as on %(posting_date)s %(posting_time)s""" % self.doc.fields) sself.doc.fields.pop('batch_bal') - - def validate_warehouse_company(self): - warehouse_company = webnotes.conn.get_value("Warehouse", self.doc.warehouse, "company") - if warehouse_company and warehouse_company != self.doc.company: - webnotes.msgprint(_("Warehouse does not belong to company.") + " (" + \ - self.doc.warehouse + ", " + self.doc.company +")", - raise_exception=InvalidWarehouseCompany) def validate_mandatory(self): mandatory = ['warehouse','posting_date','voucher_type','voucher_no','actual_qty','company'] @@ -81,7 +64,10 @@ class DocType(DocListController): msgprint("Warehouse: '%s' does not exist in the system. Please check." % self.doc.fields.get(k), raise_exception = 1) def validate_item(self): - item_det = self.get_item_details() + item_det = webnotes.conn.sql("""select name, has_batch_no, docstatus, + is_stock_item, has_serial_no, serial_no_series + from tabItem where name=%s""", + self.doc.item_code, as_dict=True)[0] if item_det.is_stock_item != 'Yes': webnotes.throw("""Item: "%s" is not a Stock Item.""" % self.doc.item_code) @@ -99,95 +85,6 @@ class DocType(DocListController): if not self.doc.stock_uom: self.doc.stock_uom = item_det.stock_uom - def get_item_details(self): - return webnotes.conn.sql("""select name, has_batch_no, docstatus, - is_stock_item, has_serial_no, serial_no_series - from tabItem where name=%s""", - self.doc.item_code, as_dict=True)[0] - - def validate_serial_no(self): - item_det = self.get_item_details() - - if item_det.has_serial_no=="No": - if self.doc.serial_no: - webnotes.throw(_("Serial Number should be blank for Non Serialized Item" + ": " + self.doc.item), - SerialNoNotRequiredError) - else: - if self.doc.serial_no: - serial_nos = get_serial_nos(self.doc.serial_no) - if cint(self.doc.actual_qty) != flt(self.doc.actual_qty): - webnotes.throw(_("Serial No qty cannot be a fraction") + \ - (": %s (%s)" % (self.doc.item_code, self.doc.actual_qty))) - if len(serial_nos) and len(serial_nos) != abs(cint(self.doc.actual_qty)): - webnotes.throw(_("Serial Nos do not match with qty") + \ - (": %s (%s)" % (self.doc.item_code, self.doc.actual_qty)), SerialNoQtyError) - - # check serial no exists, if yes then source - for serial_no in serial_nos: - if webnotes.conn.exists("Serial No", serial_no): - sr = webnotes.bean("Serial No", serial_no) - - if sr.doc.item_code!=self.doc.item_code: - webnotes.throw(_("Serial No does not belong to Item") + \ - (": %s (%s)" % (self.doc.item_code, serial_no)), SerialNoItemError) - - sr.make_controller().via_stock_ledger = True - - if self.doc.actual_qty < 0: - if sr.doc.warehouse!=self.doc.warehouse: - webnotes.throw(_("Serial No") + ": " + serial_no + - _(" does not belong to Warehouse") + ": " + self.doc.warehouse, - SerialNoWarehouseError) - - if self.doc.voucher_type in ("Delivery Note", "Sales Invoice") \ - and sr.doc.status != "Available": - webnotes.throw(_("Serial No status must be 'Available' to Deliver") - + ": " + serial_no, SerialNoStatusError) - - - sr.doc.warehouse = None - sr.save() - else: - sr.doc.warehouse = self.doc.warehouse - sr.save() - else: - if self.doc.actual_qty < 0: - # transfer out - webnotes.throw(_("Serial No must exist to transfer out.") + \ - ": " + serial_no, SerialNoNotExistsError) - else: - # transfer in - self.make_serial_no(serial_no) - else: - if item_det.serial_no_series: - from webnotes.model.doc import make_autoname - serial_nos = [] - for i in xrange(cint(self.doc.actual_qty)): - serial_nos.append(self.make_serial_no(make_autoname(item_det.serial_no_series))) - self.doc.serial_no = "\n".join(serial_nos) - else: - webnotes.throw(_("Serial Number Required for Serialized Item" + ": " + self.doc.item), - SerialNoRequiredError) - - def make_serial_no(self, serial_no): - sr = webnotes.new_bean("Serial No") - sr.doc.serial_no = serial_no - sr.doc.item_code = self.doc.item_code - sr.doc.purchase_rate = self.doc.incoming_rate - sr.doc.purchase_document_type = self.doc.voucher_type - sr.doc.purchase_document_no = self.doc.voucher_no - sr.doc.purchase_date = self.doc.posting_date - sr.doc.purchase_time = self.doc.posting_time - sr.make_controller().via_stock_ledger = True - sr.insert() - - # set warehouse - sr.doc.warehouse = self.doc.warehouse - sr.doc.status = "Available" - sr.save() - webnotes.msgprint(_("Serial No created") + ": " + sr.doc.name) - return sr.doc.name - def check_stock_frozen_date(self): stock_frozen_upto = webnotes.conn.get_value('Stock Settings', None, 'stock_frozen_upto') or '' if stock_frozen_upto: @@ -199,21 +96,6 @@ class DocType(DocListController): if not self.doc.posting_time or self.doc.posting_time == '00:0': self.doc.posting_time = '00:00' -def update_serial_nos_after_submit(controller, parenttype, parentfield): - if not hasattr(webnotes, "new_stock_ledger_entries"): - return - - for d in controller.doclist.get({"parentfield": parentfield}): - serial_no = None - for sle in webnotes.new_stock_ledger_entries: - if sle.voucher_detail_no==d.name: - serial_no = sle.serial_no - break - - if d.serial_no != serial_no: - d.serial_no = serial_no - webnotes.conn.set_value(d.doctype, d.name, "serial_no", serial_no) - def on_doctype_update(): if not webnotes.conn.sql("""show index from `tabStock Ledger Entry` where Key_name="posting_sort_index" """): diff --git a/stock/utils.py b/stock/utils.py index 8836c6c991f..1f501644ffa 100644 --- a/stock/utils.py +++ b/stock/utils.py @@ -9,6 +9,7 @@ from webnotes.defaults import get_global_default from webnotes.utils.email_lib import sendmail class UserNotAllowedForWarehouse(webnotes.ValidationError): pass +class InvalidWarehouseCompany(webnotes.ValidationError): pass def get_stock_balance_on(warehouse, posting_date=None): if not posting_date: posting_date = nowdate() @@ -216,6 +217,12 @@ def validate_warehouse_user(warehouse): if warehouse_users and not (webnotes.session.user in warehouse_users): webnotes.throw(_("Not allowed entry in Warehouse") \ + ": " + warehouse, UserNotAllowedForWarehouse) + +def validate_warehouse_company(warehouse, company): + warehouse_company = webnotes.conn.get_value("Warehouse", warehouse, "company") + if warehouse_company and warehouse_company != company: + webnotes.msgprint(_("Warehouse does not belong to company.") + " (" + \ + warehouse + ", " + company +")", raise_exception=InvalidWarehouseCompany) def get_sales_bom_buying_amount(item_code, warehouse, voucher_type, voucher_no, voucher_detail_no, stock_ledger_entries, item_sales_bom): diff --git a/support/report/maintenance_schedules/maintenance_schedules.txt b/support/report/maintenance_schedules/maintenance_schedules.txt index 525f4834ba8..766eb20151a 100644 --- a/support/report/maintenance_schedules/maintenance_schedules.txt +++ b/support/report/maintenance_schedules/maintenance_schedules.txt @@ -2,7 +2,7 @@ { "creation": "2013-05-06 14:25:21", "docstatus": 0, - "modified": "2013-05-06 14:32:47", + "modified": "2013-10-09 12:23:27", "modified_by": "Administrator", "owner": "Administrator" }, @@ -10,7 +10,7 @@ "doctype": "Report", "is_standard": "Yes", "name": "__common__", - "query": "SELECT\n ms_item.scheduled_date as \"Schedule Date:Date:120\",\n\tms_item.item_code as \"Item Code:Link/Item:120\",\n\tms_item.item_name as \"Item Name::120\",\n\tms_item.serial_no as \"Serial No::120\",\n\tms_item.incharge_name as \"Incharge::120\",\n\tms.customer_name as \"Customer:Link/Customer:120\",\n\tms.address_display as \"Customer Address::120\",\n\tms.sales_order_no as \"Sales Order:Link/Sales Order:120\",\n\tms.company as \"Company:Link/Company:120\"\n\t\nFROM\n\t`tabMaintenance Schedule` ms, `tabMaintenance Schedule Detail` ms_item\nWHERE\n\tms.name = ms_item.parent and ms.docstatus = 1\nORDER BY\n\tms_item.scheduled_date asc, ms_item.item_code asc", + "query": "SELECT\n ms_sch.scheduled_date as \"Schedule Date:Date:120\",\n\tms_sch.item_code as \"Item Code:Link/Item:120\",\n\tms_sch.item_name as \"Item Name::120\",\n\tms_sch.serial_no as \"Serial No::120\",\n\tms_sch.incharge_name as \"Incharge::120\",\n\tms.customer_name as \"Customer:Link/Customer:120\",\n\tms.address_display as \"Customer Address::120\",\n\tms_item.prevdoc_docname as \"Sales Order:Link/Sales Order:120\",\n\tms.company as \"Company:Link/Company:120\"\n\t\nFROM\n\t`tabMaintenance Schedule` ms, \n `tabMaintenance Schedule Detail` ms_sch, \n `tabMaintenance Schedule Item` ms_item\nWHERE\n\tms.name = ms_sch.parent and ms.name = ms_item.parent and ms.docstatus = 1\nORDER BY\n\tms_sch.scheduled_date asc, ms_sch.item_code asc", "ref_doctype": "Maintenance Schedule", "report_name": "Maintenance Schedules", "report_type": "Query Report" From f56d73c9bc17663b1ab0918a4164d663af70e0fc Mon Sep 17 00:00:00 2001 From: Rushabh Mehta Date: Thu, 10 Oct 2013 16:35:09 +0530 Subject: [PATCH 152/200] [minor] removed get_rate --- .../purchase_invoice/purchase_invoice.py | 8 -------- .../purchase_taxes_and_charges_master.js | 16 ++------------- .../purchase_taxes_and_charges_master.py | 7 +------ .../doctype/sales_invoice/sales_invoice.py | 8 +------- .../sales_taxes_and_charges_master.js | 18 +++-------------- .../sales_taxes_and_charges_master.py | 6 +----- .../purchase_common/purchase_common.js | 1 + .../purchase_common/purchase_common.py | 15 -------------- .../doctype/purchase_order/purchase_order.py | 7 ------- controllers/accounts_controller.py | 4 ++++ controllers/buying_controller.py | 5 ++++- public/js/controllers/accounts.js | 18 +++++++++++++++++ selling/doctype/quotation/quotation.py | 6 ------ selling/doctype/sales_common/sales_common.js | 1 + selling/doctype/sales_common/sales_common.py | 20 ------------------- selling/doctype/sales_order/sales_order.py | 3 --- stock/doctype/delivery_note/delivery_note.py | 3 --- .../material_request/material_request.py | 4 ---- .../purchase_receipt/purchase_receipt.py | 8 -------- 19 files changed, 36 insertions(+), 122 deletions(-) create mode 100644 public/js/controllers/accounts.js diff --git a/accounts/doctype/purchase_invoice/purchase_invoice.py b/accounts/doctype/purchase_invoice/purchase_invoice.py index c79bfd66487..a562c67a38a 100644 --- a/accounts/doctype/purchase_invoice/purchase_invoice.py +++ b/accounts/doctype/purchase_invoice/purchase_invoice.py @@ -88,14 +88,6 @@ class DocType(BuyingController): super(DocType, self).get_advances(self.doc.credit_to, "Purchase Invoice Advance", "advance_allocation_details", "debit") - def get_rate(self,arg): - return get_obj('Purchase Common').get_rate(arg,self) - - def get_rate1(self,acc): - rate = webnotes.conn.sql("select tax_rate from `tabAccount` where name='%s'"%(acc)) - ret={'add_tax_rate' :rate and flt(rate[0][0]) or 0 } - return ret - def check_active_purchase_items(self): for d in getlist(self.doclist, 'entries'): if d.item_code: # extra condn coz item_code is not mandatory in PV diff --git a/accounts/doctype/purchase_taxes_and_charges_master/purchase_taxes_and_charges_master.js b/accounts/doctype/purchase_taxes_and_charges_master/purchase_taxes_and_charges_master.js index 423c4e49b9d..33687736010 100644 --- a/accounts/doctype/purchase_taxes_and_charges_master/purchase_taxes_and_charges_master.js +++ b/accounts/doctype/purchase_taxes_and_charges_master/purchase_taxes_and_charges_master.js @@ -4,6 +4,8 @@ // //--------- ONLOAD ------------- +wn.require("app/js/controllers/accounts.js"); + cur_frm.cscript.onload = function(doc, cdt, cdn) { } @@ -134,20 +136,6 @@ cur_frm.fields_dict['purchase_tax_details'].grid.get_field("cost_center").get_qu } } -cur_frm.cscript.account_head = function(doc, cdt, cdn) { - var d = locals[cdt][cdn]; - if(!d.charge_type && d.account_head){ - alert("Please select Charge Type first"); - validated = false; - d.account_head = ''; - } - else if(d.account_head && d.charge_type) { - arg = "{'charge_type' : '" + d.charge_type + "', 'account_head' : '" + d.account_head + "'}"; - return get_server_fields('get_rate', arg, 'purchase_tax_details', doc, cdt, cdn, 1); - } - refresh_field('account_head',d.name,'purchase_tax_details'); -} - cur_frm.cscript.rate = function(doc, cdt, cdn) { var d = locals[cdt][cdn]; if(!d.charge_type && d.rate) { diff --git a/accounts/doctype/purchase_taxes_and_charges_master/purchase_taxes_and_charges_master.py b/accounts/doctype/purchase_taxes_and_charges_master/purchase_taxes_and_charges_master.py index 0a32fb972d6..3d003f6e932 100644 --- a/accounts/doctype/purchase_taxes_and_charges_master/purchase_taxes_and_charges_master.py +++ b/accounts/doctype/purchase_taxes_and_charges_master/purchase_taxes_and_charges_master.py @@ -14,9 +14,4 @@ from webnotes.model.code import get_obj class DocType: def __init__(self, doc, doclist=[]): self.doc = doc - self.doclist = doclist - - # Get Tax Rate if account type is Tax - # =================================================================== - def get_rate(self, arg): - return get_obj('Purchase Common').get_rate(arg, self) \ No newline at end of file + self.doclist = doclist \ No newline at end of file diff --git a/accounts/doctype/sales_invoice/sales_invoice.py b/accounts/doctype/sales_invoice/sales_invoice.py index 5c7597c4032..92c168008a1 100644 --- a/accounts/doctype/sales_invoice/sales_invoice.py +++ b/accounts/doctype/sales_invoice/sales_invoice.py @@ -264,13 +264,7 @@ class DocType(SellingController): def get_adj_percent(self, arg=''): """Fetch ref rate from item master as per selected price list""" - get_obj('Sales Common').get_adj_percent(self) - - - def get_rate(self,arg): - """Get tax rate if account type is tax""" - get_obj('Sales Common').get_rate(arg) - + get_obj('Sales Common').get_adj_percent(self) def get_comm_rate(self, sales_partner): """Get Commission rate of Sales Partner""" diff --git a/accounts/doctype/sales_taxes_and_charges_master/sales_taxes_and_charges_master.js b/accounts/doctype/sales_taxes_and_charges_master/sales_taxes_and_charges_master.js index f1a602738bf..d8f55fdd506 100644 --- a/accounts/doctype/sales_taxes_and_charges_master/sales_taxes_and_charges_master.js +++ b/accounts/doctype/sales_taxes_and_charges_master/sales_taxes_and_charges_master.js @@ -2,6 +2,9 @@ // License: GNU General Public License v3. See license.txt //--------- ONLOAD ------------- + +wn.require("app/js/controllers/accounts.js"); + cur_frm.cscript.onload = function(doc, cdt, cdn) { if(doc.doctype === "Sales Taxes and Charges Master") erpnext.add_for_territory(); @@ -142,21 +145,6 @@ cur_frm.fields_dict['other_charges'].grid.get_field("cost_center").get_query = f } } - -cur_frm.cscript.account_head = function(doc, cdt, cdn) { - var d = locals[cdt][cdn]; - if(!d.charge_type && d.account_head){ - alert("Please select Charge Type first"); - validated = false; - d.account_head = ''; - } - else if(d.account_head && d.charge_type) { - arg = "{'charge_type' : '" + d.charge_type +"', 'account_head' : '" + d.account_head + "'}"; - return get_server_fields('get_rate', arg, 'other_charges', doc, cdt, cdn, 1); - } - refresh_field('account_head',d.name,'other_charges'); -} - cur_frm.cscript.rate = function(doc, cdt, cdn) { var d = locals[cdt][cdn]; if(!d.charge_type && d.rate) { diff --git a/accounts/doctype/sales_taxes_and_charges_master/sales_taxes_and_charges_master.py b/accounts/doctype/sales_taxes_and_charges_master/sales_taxes_and_charges_master.py index 019edcb31b1..67ba9cb8add 100644 --- a/accounts/doctype/sales_taxes_and_charges_master/sales_taxes_and_charges_master.py +++ b/accounts/doctype/sales_taxes_and_charges_master/sales_taxes_and_charges_master.py @@ -6,11 +6,7 @@ import webnotes from webnotes.utils import cint from webnotes.model.controller import DocListController -class DocType(DocListController): - def get_rate(self, arg): - from webnotes.model.code import get_obj - return get_obj('Sales Common').get_rate(arg) - +class DocType(DocListController): def validate(self): if self.doc.is_default == 1: webnotes.conn.sql("""update `tabSales Taxes and Charges Master` set is_default = 0 diff --git a/buying/doctype/purchase_common/purchase_common.js b/buying/doctype/purchase_common/purchase_common.js index 433a76fba7c..023c7f3a631 100644 --- a/buying/doctype/purchase_common/purchase_common.js +++ b/buying/doctype/purchase_common/purchase_common.js @@ -8,6 +8,7 @@ wn.provide("erpnext.buying"); wn.require("app/js/transaction.js"); +wn.require("app/js/controllers/accounts.js"); erpnext.buying.BuyingController = erpnext.TransactionController.extend({ onload: function() { diff --git a/buying/doctype/purchase_common/purchase_common.py b/buying/doctype/purchase_common/purchase_common.py index c05aba48839..1d57f889100 100644 --- a/buying/doctype/purchase_common/purchase_common.py +++ b/buying/doctype/purchase_common/purchase_common.py @@ -36,13 +36,6 @@ class DocType(BuyingController): msgprint("Supplier : %s does not exists" % (name)) raise Exception - # Get Available Qty at Warehouse - def get_bin_details( self, arg = ''): - arg = eval(arg) - bin = webnotes.conn.sql("select projected_qty from `tabBin` where item_code = %s and warehouse = %s", (arg['item_code'], arg['warehouse']), as_dict=1) - ret = { 'projected_qty' : bin and flt(bin[0]['projected_qty']) or 0 } - return ret - def update_last_purchase_rate(self, obj, is_submit): """updates last_purchase_rate in item table for each item""" @@ -197,14 +190,6 @@ class DocType(BuyingController): msgprint(cstr(doctype) + ": " + cstr(submitted[0][0]) + _(" not submitted"), raise_exception=1) - def get_rate(self, arg, obj): - arg = eval(arg) - rate = webnotes.conn.sql("select account_type, tax_rate from `tabAccount` where name = %s" - , (arg['account_head']), as_dict=1) - - return {'rate': rate and (rate[0]['account_type'] == 'Tax' \ - and not arg['charge_type'] == 'Actual') and flt(rate[0]['tax_rate']) or 0 } - def get_prevdoc_date(self, obj): for d in getlist(obj.doclist, obj.fname): if d.prevdoc_doctype and d.prevdoc_docname: diff --git a/buying/doctype/purchase_order/purchase_order.py b/buying/doctype/purchase_order/purchase_order.py index 3389f7419a5..dc75466a4be 100644 --- a/buying/doctype/purchase_order/purchase_order.py +++ b/buying/doctype/purchase_order/purchase_order.py @@ -65,10 +65,6 @@ class DocType(BuyingController): } }) - # get available qty at warehouse - def get_bin_details(self, arg = ''): - return get_obj(dt='Purchase Common').get_bin_details(arg) - def get_schedule_dates(self): for d in getlist(self.doclist, 'po_details'): if d.prevdoc_detail_docname and not d.schedule_date: @@ -185,9 +181,6 @@ class DocType(BuyingController): def on_update(self): pass - def get_rate(self,arg): - return get_obj('Purchase Common').get_rate(arg,self) - @webnotes.whitelist() def make_purchase_receipt(source_name, target_doclist=None): from webnotes.model.mapper import get_mapped_doclist diff --git a/controllers/accounts_controller.py b/controllers/accounts_controller.py index 927b24980ff..f290d4d7478 100644 --- a/controllers/accounts_controller.py +++ b/controllers/accounts_controller.py @@ -423,3 +423,7 @@ class AccountsController(TransactionBase): self._abbr = webnotes.conn.get_value("Company", self.doc.company, "abbr") return self._abbr + +@webnotes.whitelist() +def get_tax_rate(account_head): + return webnotes.conn.get_value("Account", account_head, "tax_rate") diff --git a/controllers/buying_controller.py b/controllers/buying_controller.py index 25d76aa66d6..3de550c4c27 100644 --- a/controllers/buying_controller.py +++ b/controllers/buying_controller.py @@ -2,7 +2,7 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals -import webnotes +import webnotes, json from webnotes import _, msgprint from webnotes.utils import flt, _round @@ -280,3 +280,6 @@ class BuyingController(StockController): (", ".join((["%s"]*len(item_codes))),), item_codes)] return self._purchase_items + + def get_bin_details(self, arg): + return {"projected_qty": webnotes.conn.get_value("Bin", json.loads(arg), "projected_qty") or 0 } diff --git a/public/js/controllers/accounts.js b/public/js/controllers/accounts.js new file mode 100644 index 00000000000..201c47e2bb5 --- /dev/null +++ b/public/js/controllers/accounts.js @@ -0,0 +1,18 @@ + +// get tax rate +cur_frm.cscript.account_head = function(doc, cdt, cdn) { + var d = locals[cdt][cdn]; + if(!d.charge_type && d.account_head){ + msgprint("Please select Charge Type first"); + wn.model.set_value(cdt, cdn, "account_head", ""); + } else if(d.account_head && d.charge_type!=="Actual") { + wn.call({ + type:"GET", + method: "controllers.accounts_controller.get_tax_rate", + args: {"account_head":d.account_head}, + callback: function(r) { + wn.model.set_value(cdt, cdn, "rate", r.message || 0); + } + }) + } +} diff --git a/selling/doctype/quotation/quotation.py b/selling/doctype/quotation/quotation.py index b6bc45d772a..78afb97404e 100644 --- a/selling/doctype/quotation/quotation.py +++ b/selling/doctype/quotation/quotation.py @@ -56,13 +56,7 @@ class DocType(SellingController): # -------------------------------------------------------------- def get_adj_percent(self, arg=''): get_obj('Sales Common').get_adj_percent(self) - - # Get Tax rate if account type is TAX - # ----------------------------------- - def get_rate(self,arg): - return get_obj('Sales Common').get_rate(arg) - # Does not allow same item code to be entered twice # ------------------------------------------------- def validate_for_items(self): diff --git a/selling/doctype/sales_common/sales_common.js b/selling/doctype/sales_common/sales_common.js index c87e823dbab..f744faa32a6 100644 --- a/selling/doctype/sales_common/sales_common.js +++ b/selling/doctype/sales_common/sales_common.js @@ -10,6 +10,7 @@ wn.provide("erpnext.selling"); wn.require("app/js/transaction.js"); +wn.require("app/js/controllers/accounts.js"); erpnext.selling.SellingController = erpnext.TransactionController.extend({ onload: function() { diff --git a/selling/doctype/sales_common/sales_common.py b/selling/doctype/sales_common/sales_common.py index df7f1511493..634ea2a3702 100644 --- a/selling/doctype/sales_common/sales_common.py +++ b/selling/doctype/sales_common/sales_common.py @@ -86,26 +86,6 @@ class DocType(TransactionBase): if (obj.doc.price_list_currency == default_currency and flt(obj.doc.plc_conversion_rate) != 1.00) or not obj.doc.plc_conversion_rate or (obj.doc.price_list_currency != default_currency and flt(obj.doc.plc_conversion_rate) == 1.00): msgprint("Please Enter Appropriate Conversion Rate for Price List Currency to Base Currency (%s --> %s)" % (obj.doc.price_list_currency, default_currency), raise_exception = 1) - - - - # Get Tax rate if account type is TAX - # ========================================================================= - def get_rate(self, arg): - arg = eval(arg) - rate = webnotes.conn.sql("select account_type, tax_rate from `tabAccount` where name = '%s' and docstatus != 2" %(arg['account_head']), as_dict=1) - ret = {'rate' : 0} - if arg['charge_type'] == 'Actual' and rate[0]['account_type'] == 'Tax': - msgprint("You cannot select ACCOUNT HEAD of type TAX as your CHARGE TYPE is 'ACTUAL'") - ret = { - 'account_head' : '' - } - elif rate[0]['account_type'] in ['Tax', 'Chargeable'] and not arg['charge_type'] == 'Actual': - ret = { - 'rate' : rate and flt(rate[0]['tax_rate']) or 0 - } - return ret - def get_item_list(self, obj, is_stopped=0): """get item list""" diff --git a/selling/doctype/sales_order/sales_order.py b/selling/doctype/sales_order/sales_order.py index 0cdca58ce9b..1c22c08a3b6 100644 --- a/selling/doctype/sales_order/sales_order.py +++ b/selling/doctype/sales_order/sales_order.py @@ -38,9 +38,6 @@ class DocType(SellingController): def get_available_qty(self,args): return get_obj('Sales Common').get_available_qty(eval(args)) - def get_rate(self,arg): - return get_obj('Sales Common').get_rate(arg) - def validate_mandatory(self): # validate transaction date v/s delivery date if self.doc.delivery_date: diff --git a/stock/doctype/delivery_note/delivery_note.py b/stock/doctype/delivery_note/delivery_note.py index b20e790af76..281908598fb 100644 --- a/stock/doctype/delivery_note/delivery_note.py +++ b/stock/doctype/delivery_note/delivery_note.py @@ -66,9 +66,6 @@ class DocType(SellingController): """Re-calculates Basic Rate & amount based on Price List Selected""" get_obj('Sales Common').get_adj_percent(self) - def get_rate(self,arg): - return get_obj('Sales Common').get_rate(arg) - def so_required(self): """check in manage account if sales order required or not""" if webnotes.conn.get_value("Selling Settings", None, 'so_required') == 'Yes': diff --git a/stock/doctype/material_request/material_request.py b/stock/doctype/material_request/material_request.py index d1672ba12c1..7aea3364e4a 100644 --- a/stock/doctype/material_request/material_request.py +++ b/stock/doctype/material_request/material_request.py @@ -20,10 +20,6 @@ class DocType(BuyingController): self.tname = 'Material Request Item' self.fname = 'indent_details' - # get available qty at warehouse - def get_bin_details(self, arg = ''): - return get_obj(dt='Purchase Common').get_bin_details(arg) - def check_if_already_pulled(self): pass#if self.[d.sales_order_no for d in getlist(self.doclist, 'indent_details')] diff --git a/stock/doctype/purchase_receipt/purchase_receipt.py b/stock/doctype/purchase_receipt/purchase_receipt.py index 6169b1d9166..1e1f1eaf869 100644 --- a/stock/doctype/purchase_receipt/purchase_receipt.py +++ b/stock/doctype/purchase_receipt/purchase_receipt.py @@ -38,10 +38,6 @@ class DocType(BuyingController): total_qty = sum((item.qty for item in self.doclist.get({"parentfield": "purchase_receipt_details"}))) self.doc.fields["__billing_complete"] = billed_qty[0][0] == total_qty - # get available qty at warehouse - def get_bin_details(self, arg = ''): - return get_obj(dt='Purchase Common').get_bin_details(arg) - def validate(self): super(DocType, self).validate() @@ -290,10 +286,6 @@ class DocType(BuyingController): bin = webnotes.conn.sql("select actual_qty from `tabBin` where item_code = %s and warehouse = %s", (d.rm_item_code, self.doc.supplier_warehouse), as_dict = 1) d.current_stock = bin and flt(bin[0]['actual_qty']) or 0 - - def get_rate(self,arg): - return get_obj('Purchase Common').get_rate(arg,self) - def get_gl_entries_for_stock(self, warehouse_account=None): against_stock_account = self.get_company_default("stock_received_but_not_billed") From 2eec1eb9a68510f708244e75879e084bf2750617 Mon Sep 17 00:00:00 2001 From: Rushabh Mehta Date: Thu, 10 Oct 2013 17:03:56 +0530 Subject: [PATCH 153/200] [minor] removed prevdoc_date --- .../purchase_common/purchase_common.py | 7 ------- .../doctype/purchase_order/purchase_order.js | 4 ++-- .../doctype/purchase_order/purchase_order.py | 1 - .../purchase_order_item.txt | 17 +---------------- .../supplier_quotation/supplier_quotation.py | 1 - .../supplier_quotation_item.txt | 17 +---------------- controllers/buying_controller.py | 4 +--- .../installation_note/installation_note.py | 1 - .../installation_note_item.txt | 14 +------------- selling/doctype/sales_common/sales_common.py | 19 ------------------- stock/doctype/delivery_note/delivery_note.js | 4 ++-- stock/doctype/delivery_note/delivery_note.py | 2 -- .../delivery_note_item/delivery_note_item.txt | 15 +-------------- .../purchase_receipt/purchase_receipt.py | 1 - .../purchase_receipt_item.txt | 15 +-------------- 15 files changed, 10 insertions(+), 112 deletions(-) diff --git a/buying/doctype/purchase_common/purchase_common.py b/buying/doctype/purchase_common/purchase_common.py index 1d57f889100..8637e5fb43a 100644 --- a/buying/doctype/purchase_common/purchase_common.py +++ b/buying/doctype/purchase_common/purchase_common.py @@ -189,10 +189,3 @@ class DocType(BuyingController): if not submitted: msgprint(cstr(doctype) + ": " + cstr(submitted[0][0]) + _(" not submitted"), raise_exception=1) - - def get_prevdoc_date(self, obj): - for d in getlist(obj.doclist, obj.fname): - if d.prevdoc_doctype and d.prevdoc_docname: - dt = webnotes.conn.sql("select transaction_date from `tab%s` where name = %s" - % (d.prevdoc_doctype, '%s'), (d.prevdoc_docname)) - d.prevdoc_date = dt and dt[0][0].strftime('%Y-%m-%d') or '' \ No newline at end of file diff --git a/buying/doctype/purchase_order/purchase_order.js b/buying/doctype/purchase_order/purchase_order.js index 9967f15a50b..f32f11a2a6e 100644 --- a/buying/doctype/purchase_order/purchase_order.js +++ b/buying/doctype/purchase_order/purchase_order.js @@ -185,9 +185,9 @@ cur_frm.pformat.indent_no = function(doc, cdt, cdn){ if(cl[i].prevdoc_doctype == 'Material Request' && cl[i].prevdoc_docname && prevdoc_list.indexOf(cl[i].prevdoc_docname) == -1) { prevdoc_list.push(cl[i].prevdoc_docname); if(prevdoc_list.length ==1) - out += make_row(cl[i].prevdoc_doctype, cl[i].prevdoc_docname, cl[i].prevdoc_date,0); + out += make_row(cl[i].prevdoc_doctype, cl[i].prevdoc_docname, null,0); else - out += make_row('', cl[i].prevdoc_docname, cl[i].prevdoc_date,0); + out += make_row('', cl[i].prevdoc_docname,null,0); } } } diff --git a/buying/doctype/purchase_order/purchase_order.py b/buying/doctype/purchase_order/purchase_order.py index dc75466a4be..cf207bb7477 100644 --- a/buying/doctype/purchase_order/purchase_order.py +++ b/buying/doctype/purchase_order/purchase_order.py @@ -41,7 +41,6 @@ class DocType(BuyingController): pc_obj = get_obj(dt='Purchase Common') pc_obj.validate_for_items(self) - pc_obj.get_prevdoc_date(self) self.check_for_stopped_status(pc_obj) self.validate_uom_is_integer("uom", "qty") diff --git a/buying/doctype/purchase_order_item/purchase_order_item.txt b/buying/doctype/purchase_order_item/purchase_order_item.txt index 36b81d2c1fc..fade98fa980 100755 --- a/buying/doctype/purchase_order_item/purchase_order_item.txt +++ b/buying/doctype/purchase_order_item/purchase_order_item.txt @@ -2,7 +2,7 @@ { "creation": "2013-05-24 19:29:06", "docstatus": 0, - "modified": "2013-08-07 14:44:12", + "modified": "2013-10-10 17:01:57", "modified_by": "Administrator", "owner": "Administrator" }, @@ -306,21 +306,6 @@ "search_index": 1, "width": "120px" }, - { - "doctype": "DocField", - "fieldname": "prevdoc_date", - "fieldtype": "Date", - "hidden": 1, - "in_filter": 1, - "in_list_view": 0, - "label": "Material Request Date", - "no_copy": 1, - "oldfieldname": "prevdoc_date", - "oldfieldtype": "Date", - "print_hide": 1, - "read_only": 1, - "search_index": 0 - }, { "doctype": "DocField", "fieldname": "prevdoc_detail_docname", diff --git a/buying/doctype/supplier_quotation/supplier_quotation.py b/buying/doctype/supplier_quotation/supplier_quotation.py index c3d2f78451a..8c5224e30ac 100644 --- a/buying/doctype/supplier_quotation/supplier_quotation.py +++ b/buying/doctype/supplier_quotation/supplier_quotation.py @@ -54,7 +54,6 @@ class DocType(BuyingController): def validate_common(self): pc = get_obj('Purchase Common') pc.validate_for_items(self) - pc.get_prevdoc_date(self) @webnotes.whitelist() def make_purchase_order(source_name, target_doclist=None): diff --git a/buying/doctype/supplier_quotation_item/supplier_quotation_item.txt b/buying/doctype/supplier_quotation_item/supplier_quotation_item.txt index 1d162915ef4..515cdb2a34f 100644 --- a/buying/doctype/supplier_quotation_item/supplier_quotation_item.txt +++ b/buying/doctype/supplier_quotation_item/supplier_quotation_item.txt @@ -2,7 +2,7 @@ { "creation": "2013-05-22 12:43:10", "docstatus": 0, - "modified": "2013-08-07 14:44:18", + "modified": "2013-10-10 17:02:11", "modified_by": "Administrator", "owner": "Administrator" }, @@ -259,21 +259,6 @@ "search_index": 1, "width": "120px" }, - { - "doctype": "DocField", - "fieldname": "prevdoc_date", - "fieldtype": "Date", - "hidden": 1, - "in_filter": 1, - "in_list_view": 0, - "label": "Material Request Date", - "no_copy": 1, - "oldfieldname": "prevdoc_date", - "oldfieldtype": "Date", - "print_hide": 1, - "read_only": 1, - "search_index": 0 - }, { "doctype": "DocField", "fieldname": "prevdoc_detail_docname", diff --git a/controllers/buying_controller.py b/controllers/buying_controller.py index 3de550c4c27..2e55aee1357 100644 --- a/controllers/buying_controller.py +++ b/controllers/buying_controller.py @@ -14,6 +14,7 @@ from controllers.stock_controller import StockController class WrongWarehouseCompany(Exception): pass class BuyingController(StockController): + def onload_post_render(self): # contact, address, item details self.set_missing_values() @@ -280,6 +281,3 @@ class BuyingController(StockController): (", ".join((["%s"]*len(item_codes))),), item_codes)] return self._purchase_items - - def get_bin_details(self, arg): - return {"projected_qty": webnotes.conn.get_value("Bin", json.loads(arg), "projected_qty") or 0 } diff --git a/selling/doctype/installation_note/installation_note.py b/selling/doctype/installation_note/installation_note.py index ca47043e28c..02b724719c1 100644 --- a/selling/doctype/installation_note/installation_note.py +++ b/selling/doctype/installation_note/installation_note.py @@ -38,7 +38,6 @@ class DocType(TransactionBase): self.check_item_table() sales_com_obj = get_obj(dt = 'Sales Common') sales_com_obj.check_active_sales_items(self) - sales_com_obj.get_prevdoc_date(self) def validate_fiscal_year(self): from accounts.utils import validate_fiscal_year diff --git a/selling/doctype/installation_note_item/installation_note_item.txt b/selling/doctype/installation_note_item/installation_note_item.txt index 02871ad7343..7435d461b41 100644 --- a/selling/doctype/installation_note_item/installation_note_item.txt +++ b/selling/doctype/installation_note_item/installation_note_item.txt @@ -2,7 +2,7 @@ { "creation": "2013-02-22 01:27:51", "docstatus": 0, - "modified": "2013-07-10 14:54:09", + "modified": "2013-10-10 17:02:31", "modified_by": "Administrator", "owner": "Administrator" }, @@ -48,18 +48,6 @@ "read_only": 1, "width": "300px" }, - { - "doctype": "DocField", - "fieldname": "prevdoc_date", - "fieldtype": "Date", - "hidden": 0, - "in_list_view": 1, - "label": "Delivery Date", - "oldfieldname": "prevdoc_date", - "oldfieldtype": "Date", - "print_hide": 0, - "read_only": 1 - }, { "doctype": "DocField", "fieldname": "serial_no", diff --git a/selling/doctype/sales_common/sales_common.py b/selling/doctype/sales_common/sales_common.py index 634ea2a3702..01718dd3f0b 100644 --- a/selling/doctype/sales_common/sales_common.py +++ b/selling/doctype/sales_common/sales_common.py @@ -298,25 +298,6 @@ class DocType(TransactionBase): exact_outstanding = flt(tot_outstanding) + flt(grand_total) get_obj('Account',acc_head[0][0]).check_credit_limit(acc_head[0][0], obj.doc.company, exact_outstanding) - def get_prevdoc_date(self, obj): - for d in getlist(obj.doclist, obj.fname): - date_field = None - - pdoctype, pname = d.prevdoc_doctype, d.prevdoc_docname - - if d.against_sales_invoice: - pdoctype, pname = "Sales Invoice", d.against_sales_invoice - elif d.against_sales_order: - pdoctype, pname = "Sales Order", d.against_sales_order - - if pdoctype and pname: - if pdoctype in ["Sales Invoice", "Delivery Note"]: - date_field = "posting_date" - else: - date_field = "transaction_date" - - d.prevdoc_date = webnotes.conn.get_value(pdoctype, pname, date_field) - def get_batch_no(doctype, txt, searchfield, start, page_len, filters): from controllers.queries import get_match_cond diff --git a/stock/doctype/delivery_note/delivery_note.js b/stock/doctype/delivery_note/delivery_note.js index edfd6ff7db2..29b3e47b32e 100644 --- a/stock/doctype/delivery_note/delivery_note.js +++ b/stock/doctype/delivery_note/delivery_note.js @@ -184,9 +184,9 @@ cur_frm.pformat.sales_order_no= function(doc, cdt, cdn){ if(cl[i].against_sales_order && prevdoc_list.indexOf(cl[i].against_sales_order) == -1) { prevdoc_list.push(cl[i].against_sales_order); if(prevdoc_list.length ==1) - out += make_row("Sales Order", cl[i].against_sales_order, cl[i].prevdoc_date, 0); + out += make_row("Sales Order", cl[i].against_sales_order, null, 0); else - out += make_row('', cl[i].against_sales_order, cl[i].prevdoc_date,0); + out += make_row('', cl[i].against_sales_order, null,0); } } } diff --git a/stock/doctype/delivery_note/delivery_note.py b/stock/doctype/delivery_note/delivery_note.py index 281908598fb..deaf024a2ea 100644 --- a/stock/doctype/delivery_note/delivery_note.py +++ b/stock/doctype/delivery_note/delivery_note.py @@ -86,7 +86,6 @@ class DocType(SellingController): sales_com_obj = get_obj(dt = 'Sales Common') sales_com_obj.check_stop_sales_order(self) sales_com_obj.check_active_sales_items(self) - sales_com_obj.get_prevdoc_date(self) self.validate_for_items() self.validate_warehouse() self.validate_uom_is_integer("stock_uom", "qty") @@ -366,7 +365,6 @@ def make_sales_invoice(source_name, target_doclist=None): def make_installation_note(source_name, target_doclist=None): def update_item(obj, target, source_parent): target.qty = flt(obj.qty) - flt(obj.installed_qty) - target.prevdoc_date = source_parent.posting_date target.serial_no = obj.serial_no doclist = get_mapped_doclist("Delivery Note", source_name, { diff --git a/stock/doctype/delivery_note_item/delivery_note_item.txt b/stock/doctype/delivery_note_item/delivery_note_item.txt index 4162187fdcd..8d1792d7c14 100644 --- a/stock/doctype/delivery_note_item/delivery_note_item.txt +++ b/stock/doctype/delivery_note_item/delivery_note_item.txt @@ -2,7 +2,7 @@ { "creation": "2013-04-22 13:15:44", "docstatus": 0, - "modified": "2013-10-03 11:09:48", + "modified": "2013-10-10 17:03:11", "modified_by": "Administrator", "owner": "Administrator" }, @@ -362,19 +362,6 @@ "label": "Against Sales Invoice", "options": "Sales Invoice" }, - { - "doctype": "DocField", - "fieldname": "prevdoc_date", - "fieldtype": "Date", - "hidden": 1, - "in_filter": 1, - "label": "Against Document Date", - "no_copy": 1, - "oldfieldname": "prevdoc_date", - "oldfieldtype": "Date", - "print_hide": 1, - "read_only": 1 - }, { "doctype": "DocField", "fieldname": "prevdoc_detail_docname", diff --git a/stock/doctype/purchase_receipt/purchase_receipt.py b/stock/doctype/purchase_receipt/purchase_receipt.py index 1e1f1eaf869..2dd450febb9 100644 --- a/stock/doctype/purchase_receipt/purchase_receipt.py +++ b/stock/doctype/purchase_receipt/purchase_receipt.py @@ -59,7 +59,6 @@ class DocType(BuyingController): pc_obj = get_obj(dt='Purchase Common') pc_obj.validate_for_items(self) - pc_obj.get_prevdoc_date(self) self.check_for_stopped_status(pc_obj) # sub-contracting diff --git a/stock/doctype/purchase_receipt_item/purchase_receipt_item.txt b/stock/doctype/purchase_receipt_item/purchase_receipt_item.txt index ce491689ec6..9c0d0fbb11c 100755 --- a/stock/doctype/purchase_receipt_item/purchase_receipt_item.txt +++ b/stock/doctype/purchase_receipt_item/purchase_receipt_item.txt @@ -2,7 +2,7 @@ { "creation": "2013-05-24 19:29:10", "docstatus": 0, - "modified": "2013-09-20 11:36:55", + "modified": "2013-10-10 17:02:51", "modified_by": "Administrator", "owner": "Administrator" }, @@ -424,19 +424,6 @@ "search_index": 1, "width": "150px" }, - { - "doctype": "DocField", - "fieldname": "prevdoc_date", - "fieldtype": "Date", - "hidden": 1, - "in_filter": 1, - "label": "Purchase Order Date", - "no_copy": 1, - "oldfieldname": "prevdoc_date", - "oldfieldtype": "Date", - "print_hide": 1, - "read_only": 1 - }, { "doctype": "DocField", "fieldname": "rm_supp_cost", From 9106221ea4ffc049da7bf31ca2c71531b6b248b5 Mon Sep 17 00:00:00 2001 From: Anand Doshi Date: Thu, 10 Oct 2013 18:43:34 +0530 Subject: [PATCH 154/200] [minor] fixes after merge with master --- .../sales_invoice/test_sales_invoice.py | 10 ++--- .../voucher_import_tool.py | 14 +++---- .../purchase_order/test_purchase_order.py | 6 +-- controllers/buying_controller.py | 2 - .../doctype/backup_manager/backup_dropbox.py | 4 +- .../delivery_note/test_delivery_note.py | 6 +-- .../material_request/test_material_request.py | 4 +- .../purchase_receipt/purchase_receipt.py | 2 +- .../purchase_receipt/test_purchase_receipt.py | 3 +- stock/doctype/serial_no/serial_no.py | 40 +++++++++++-------- stock/doctype/stock_entry/stock_entry.py | 2 +- stock/doctype/stock_entry/test_stock_entry.py | 7 ++-- .../stock_ledger_entry/stock_ledger_entry.py | 6 +-- stock/utils.py | 18 ++++----- 14 files changed, 64 insertions(+), 60 deletions(-) diff --git a/accounts/doctype/sales_invoice/test_sales_invoice.py b/accounts/doctype/sales_invoice/test_sales_invoice.py index dee098a3e4f..9f5b95cd79c 100644 --- a/accounts/doctype/sales_invoice/test_sales_invoice.py +++ b/accounts/doctype/sales_invoice/test_sales_invoice.py @@ -641,8 +641,8 @@ class TestSalesInvoice(unittest.TestCase): return new_si - # if yearly, test 3 repetitions, else test 13 repetitions - count = 3 if no_of_months == 12 else 13 + # if yearly, test 1 repetition, else test 5 repetitions + count = 1 if (no_of_months == 12) else 5 for i in xrange(count): base_si = _test(i) @@ -653,7 +653,7 @@ class TestSalesInvoice(unittest.TestCase): def test_serialized(self): from stock.doctype.stock_entry.test_stock_entry import make_serialized_item - from stock.doctype.stock_ledger_entry.stock_ledger_entry import get_serial_nos + from stock.doctype.serial_no.serial_no import get_serial_nos se = make_serialized_item() serial_nos = get_serial_nos(se.doclist[1].serial_no) @@ -674,7 +674,7 @@ class TestSalesInvoice(unittest.TestCase): return si def test_serialized_cancel(self): - from stock.doctype.stock_ledger_entry.stock_ledger_entry import get_serial_nos + from stock.doctype.serial_no.serial_no import get_serial_nos si = self.test_serialized() si.cancel() @@ -686,7 +686,7 @@ class TestSalesInvoice(unittest.TestCase): "delivery_document_no")) def test_serialize_status(self): - from stock.doctype.stock_ledger_entry.stock_ledger_entry import SerialNoStatusError, get_serial_nos + from stock.doctype.serial_no.serial_no import SerialNoStatusError, get_serial_nos from stock.doctype.stock_entry.test_stock_entry import make_serialized_item se = make_serialized_item() diff --git a/accounts/page/voucher_import_tool/voucher_import_tool.py b/accounts/page/voucher_import_tool/voucher_import_tool.py index 9425afc7d0f..14e30be7a9e 100644 --- a/accounts/page/voucher_import_tool/voucher_import_tool.py +++ b/accounts/page/voucher_import_tool/voucher_import_tool.py @@ -64,10 +64,10 @@ def upload(): data, start_idx = get_data(rows, company_abbr, rows[0][0]) except Exception, e: - err_msg = webnotes.message_log and "
    ".join(webnotes.message_log) or cstr(e) + err_msg = webnotes.local.message_log and "
    ".join(webnotes.local.message_log) or cstr(e) messages.append("""

    %s

    """ % (err_msg or "No message")) webnotes.errprint(webnotes.getTraceback()) - webnotes.message_log = [] + webnotes.local.message_log = [] return messages return import_vouchers(common_values, data, start_idx, rows[0][0]) @@ -117,11 +117,11 @@ def import_vouchers(common_values, data, start_idx, import_type): d = data[i][0] if import_type == "Voucher Import: Two Accounts" and flt(d.get("amount")) == 0: - webnotes.message_log = ["Amount not specified"] + webnotes.local.message_log = ["Amount not specified"] raise Exception elif import_type == "Voucher Import: Multiple Accounts" and \ (flt(d.get("total_debit")) == 0 or flt(d.get("total_credit")) == 0): - webnotes.message_log = ["Total Debit and Total Credit amount can not be zero"] + webnotes.local.message_log = ["Total Debit and Total Credit amount can not be zero"] raise Exception else: d.posting_date = parse_date(d.posting_date) @@ -174,7 +174,7 @@ def import_vouchers(common_values, data, start_idx, import_type): details.append(detail) if not details: - webnotes.message_log = ["""No accounts found. + webnotes.local.message_log = ["""No accounts found. If you entered accounts correctly, please check template once"""] raise Exception @@ -193,12 +193,12 @@ def import_vouchers(common_values, data, start_idx, import_type): webnotes.conn.commit() except Exception, e: webnotes.conn.rollback() - err_msg = webnotes.message_log and "
    ".join(webnotes.message_log) or cstr(e) + err_msg = webnotes.local.message_log and "
    ".join(webnotes.local.message_log) or cstr(e) messages.append("""

    [row #%s] %s failed: %s

    """ % ((start_idx + 1) + i, jv.name or "", err_msg or "No message")) messages.append("

    All transactions rolled back

    ") webnotes.errprint(webnotes.getTraceback()) - webnotes.message_log = [] + webnotes.local.message_log = [] return messages diff --git a/buying/doctype/purchase_order/test_purchase_order.py b/buying/doctype/purchase_order/test_purchase_order.py index cef5e4a207b..e9a9c348a62 100644 --- a/buying/doctype/purchase_order/test_purchase_order.py +++ b/buying/doctype/purchase_order/test_purchase_order.py @@ -98,12 +98,12 @@ class TestPurchaseOrder(unittest.TestCase): self.assertEquals(len(po.doclist.get({"parentfield": "po_raw_material_details"})), 2) def test_warehouse_company_validation(self): - from controllers.buying_controller import WrongWarehouseCompany + from stock.utils import InvalidWarehouseCompany po = webnotes.bean(copy=test_records[0]) po.doc.company = "_Test Company 1" po.doc.conversion_rate = 0.0167 - self.assertRaises(WrongWarehouseCompany, po.insert) - + self.assertRaises(InvalidWarehouseCompany, po.insert) + def test_uom_integer_validation(self): from utilities.transaction_base import UOMMustBeIntegerError po = webnotes.bean(copy=test_records[0]) diff --git a/controllers/buying_controller.py b/controllers/buying_controller.py index 2e55aee1357..c42eda50bc9 100644 --- a/controllers/buying_controller.py +++ b/controllers/buying_controller.py @@ -11,8 +11,6 @@ from setup.utils import get_company_currency from controllers.stock_controller import StockController -class WrongWarehouseCompany(Exception): pass - class BuyingController(StockController): def onload_post_render(self): diff --git a/setup/doctype/backup_manager/backup_dropbox.py b/setup/doctype/backup_manager/backup_dropbox.py index b4a8f66d4c0..3d3f428260a 100644 --- a/setup/doctype/backup_manager/backup_dropbox.py +++ b/setup/doctype/backup_manager/backup_dropbox.py @@ -61,8 +61,8 @@ def dropbox_callback(oauth_token=None, not_approved=False): allowed = 0 message = "Dropbox Access not approved." - webnotes.message_title = "Dropbox Approval" - webnotes.message = "

    %s

    Please close this window.

    " % message + webnotes.local.message_title = "Dropbox Approval" + webnotes.local.message = "

    %s

    Please close this window.

    " % message webnotes.conn.commit() webnotes.response['type'] = 'page' diff --git a/stock/doctype/delivery_note/test_delivery_note.py b/stock/doctype/delivery_note/test_delivery_note.py index 7c525504ae4..ca95a506026 100644 --- a/stock/doctype/delivery_note/test_delivery_note.py +++ b/stock/doctype/delivery_note/test_delivery_note.py @@ -160,7 +160,7 @@ class TestDeliveryNote(unittest.TestCase): def test_serialized(self): from stock.doctype.stock_entry.test_stock_entry import make_serialized_item - from stock.doctype.stock_ledger_entry.stock_ledger_entry import get_serial_nos + from stock.doctype.serial_no.serial_no import get_serial_nos se = make_serialized_item() serial_nos = get_serial_nos(se.doclist[1].serial_no) @@ -180,7 +180,7 @@ class TestDeliveryNote(unittest.TestCase): return dn def test_serialized_cancel(self): - from stock.doctype.stock_ledger_entry.stock_ledger_entry import get_serial_nos + from stock.doctype.serial_no.serial_no import get_serial_nos dn = self.test_serialized() dn.cancel() @@ -192,7 +192,7 @@ class TestDeliveryNote(unittest.TestCase): "delivery_document_no")) def test_serialize_status(self): - from stock.doctype.stock_ledger_entry.stock_ledger_entry import SerialNoStatusError, get_serial_nos + from stock.doctype.serial_no.serial_no import SerialNoStatusError, get_serial_nos from stock.doctype.stock_entry.test_stock_entry import make_serialized_item se = make_serialized_item() diff --git a/stock/doctype/material_request/test_material_request.py b/stock/doctype/material_request/test_material_request.py index 8ebad15810a..13fdd02c3ca 100644 --- a/stock/doctype/material_request/test_material_request.py +++ b/stock/doctype/material_request/test_material_request.py @@ -315,10 +315,10 @@ class TestMaterialRequest(unittest.TestCase): self.assertRaises(webnotes.MappingMismatchError, se.insert) def test_warehouse_company_validation(self): - from controllers.buying_controller import WrongWarehouseCompany + from stock.utils import InvalidWarehouseCompany mr = webnotes.bean(copy=test_records[0]) mr.doc.company = "_Test Company 1" - self.assertRaises(WrongWarehouseCompany, mr.insert) + self.assertRaises(InvalidWarehouseCompany, mr.insert) test_dependencies = ["Currency Exchange"] test_records = [ diff --git a/stock/doctype/purchase_receipt/purchase_receipt.py b/stock/doctype/purchase_receipt/purchase_receipt.py index 2dd450febb9..537d75d339e 100644 --- a/stock/doctype/purchase_receipt/purchase_receipt.py +++ b/stock/doctype/purchase_receipt/purchase_receipt.py @@ -242,7 +242,7 @@ class DocType(BuyingController): self.update_stock() from stock.doctype.serial_no.serial_no import update_serial_nos_after_submit - update_serial_nos_after_submit(self, "Purchase Receipt", "purchase_receipt_details") + update_serial_nos_after_submit(self, "purchase_receipt_details") purchase_controller.update_last_purchase_rate(self, 1) diff --git a/stock/doctype/purchase_receipt/test_purchase_receipt.py b/stock/doctype/purchase_receipt/test_purchase_receipt.py index 010c29be79f..613dfbc6b00 100644 --- a/stock/doctype/purchase_receipt/test_purchase_receipt.py +++ b/stock/doctype/purchase_receipt/test_purchase_receipt.py @@ -104,6 +104,7 @@ class TestPurchaseReceipt(unittest.TestCase): pr.doclist[1].received_qty = 1 pr.insert() pr.submit() + self.assertEquals(webnotes.conn.get_value("Serial No", pr.doclist[1].serial_no, "supplier"), pr.doc.supplier) @@ -112,7 +113,7 @@ class TestPurchaseReceipt(unittest.TestCase): def test_serial_no_cancel(self): pr = self.test_serial_no_supplier() pr.cancel() - + self.assertFalse(webnotes.conn.get_value("Serial No", pr.doclist[1].serial_no, "warehouse")) diff --git a/stock/doctype/serial_no/serial_no.py b/stock/doctype/serial_no/serial_no.py index 93836d64e48..61b28417870 100644 --- a/stock/doctype/serial_no/serial_no.py +++ b/stock/doctype/serial_no/serial_no.py @@ -37,11 +37,8 @@ class DocType(StockController): self.validate_warehouse() self.validate_item() - if self.via_stock_ledger: - self.set_status() - self.set_purchase_details() - self.set_sales_details() - + self.on_stock_ledger_entry() + def validate_amc_status(self): """ validate amc status @@ -118,7 +115,7 @@ class DocType(StockController): and ifnull(is_cancelled, 'No')='No' order by name asc limit 1""", ("%%%s%%" % (self.doc.name+"\n"), "%%%s%%" % ("\n"+self.doc.name), self.doc.name, self.doc.item_code), as_dict=1) - + if purchase_sle: self.doc.purchase_document_type = purchase_sle[0].voucher_type self.doc.purchase_document_no = purchase_sle[0].voucher_no @@ -181,6 +178,12 @@ class DocType(StockController): webnotes.conn.sql("""update `tab%s` set serial_no = %s where name=%s""" % (dt[0], '%s', '%s'), ('\n'.join(serial_nos), item[0])) + + def on_stock_ledger_entry(self): + if self.via_stock_ledger and not self.doc.fields.get("__islocal"): + self.set_status() + self.set_purchase_details() + self.set_sales_details() def process_serial_no(sle): item_det = get_item_details(sle.item_code) @@ -233,6 +236,14 @@ def validate_serial_no(sle, item_det): + sle.item_code), SerialNoRequiredError) def update_serial_nos(sle, item_det): + if not sle.serial_no and sle.actual_qty > 0 and item_det.serial_no_series: + from webnotes.model.doc import make_autoname + serial_nos = [] + for i in xrange(cint(sle.actual_qty)): + serial_nos.append(make_autoname(item_det.serial_no_series)) + + webnotes.conn.set(sle, "serial_no", "\n".join(serial_nos)) + if sle.serial_no: serial_nos = get_serial_nos(sle.serial_no) for serial_no in serial_nos: @@ -243,12 +254,6 @@ def update_serial_nos(sle, item_det): sr.save() elif sle.actual_qty > 0: make_serial_no(serial_no, sle) - elif sle.actual_qty > 0 and item_det.serial_no_series: - from webnotes.model.doc import make_autoname - serial_nos = [] - for i in xrange(cint(sle.actual_qty)): - serial_nos.append(make_serial_no(make_autoname(item_det.serial_no_series), sle)) - sle.serial_no = "\n".join(serial_nos) def get_item_details(item_code): return webnotes.conn.sql("""select name, has_batch_no, docstatus, @@ -270,13 +275,16 @@ def make_serial_no(serial_no, sle): webnotes.msgprint(_("Serial No created") + ": " + sr.doc.name) return sr.doc.name -def update_serial_nos_after_submit(controller, parenttype, parentfield): - if not hasattr(webnotes, "new_stock_ledger_entries"): - return +def update_serial_nos_after_submit(controller, parentfield): + stock_ledger_entries = webnotes.conn.sql("""select voucher_detail_no, serial_no + from `tabStock Ledger Entry` where voucher_type=%s and voucher_no=%s""", + (controller.doc.doctype, controller.doc.name), as_dict=True) + if not stock_ledger_entries: return + for d in controller.doclist.get({"parentfield": parentfield}): serial_no = None - for sle in webnotes.new_stock_ledger_entries: + for sle in stock_ledger_entries: if sle.voucher_detail_no==d.name: serial_no = sle.serial_no break diff --git a/stock/doctype/stock_entry/stock_entry.py b/stock/doctype/stock_entry/stock_entry.py index 0117864a1be..63cfd2be90f 100644 --- a/stock/doctype/stock_entry/stock_entry.py +++ b/stock/doctype/stock_entry/stock_entry.py @@ -53,7 +53,7 @@ class DocType(StockController): self.update_stock_ledger() from stock.doctype.serial_no.serial_no import update_serial_nos_after_submit - update_serial_nos_after_submit(self, "Stock Entry", "mtn_details") + update_serial_nos_after_submit(self, "mtn_details") self.update_production_order(1) self.make_gl_entries() diff --git a/stock/doctype/stock_entry/test_stock_entry.py b/stock/doctype/stock_entry/test_stock_entry.py index b41a6269ad9..f01a83b2f72 100644 --- a/stock/doctype/stock_entry/test_stock_entry.py +++ b/stock/doctype/stock_entry/test_stock_entry.py @@ -44,9 +44,10 @@ class TestStockEntry(unittest.TestCase): def test_warehouse_company_validation(self): self._clear_stock_account_balance() - webnotes.session.user = "test2@example.com" webnotes.bean("Profile", "test2@example.com").get_controller()\ .add_roles("Sales User", "Sales Manager", "Material User", "Material Manager") + + webnotes.session.user = "test2@example.com" from stock.utils import InvalidWarehouseCompany st1 = webnotes.bean(copy=test_records[0]) @@ -59,13 +60,13 @@ class TestStockEntry(unittest.TestCase): def test_warehouse_user(self): from stock.utils import UserNotAllowedForWarehouse - webnotes.session.user = "test@example.com" webnotes.bean("Profile", "test@example.com").get_controller()\ .add_roles("Sales User", "Sales Manager", "Material User", "Material Manager") webnotes.bean("Profile", "test2@example.com").get_controller()\ .add_roles("Sales User", "Sales Manager", "Material User", "Material Manager") - + + webnotes.session.user = "test@example.com" st1 = webnotes.bean(copy=test_records[0]) st1.doc.company = "_Test Company 1" st1.doclist[1].t_warehouse="_Test Warehouse 2 - _TC1" diff --git a/stock/doctype/stock_ledger_entry/stock_ledger_entry.py b/stock/doctype/stock_ledger_entry/stock_ledger_entry.py index 8fef889f724..c7703ed7ee6 100644 --- a/stock/doctype/stock_ledger_entry/stock_ledger_entry.py +++ b/stock/doctype/stock_ledger_entry/stock_ledger_entry.py @@ -14,10 +14,6 @@ class DocType(DocListController): def validate(self): from stock.utils import validate_warehouse_user, validate_warehouse_company - if not hasattr(webnotes, "new_stock_ledger_entries"): - webnotes.new_stock_ledger_entries = [] - - webnotes.new_stock_ledger_entries.append(self.doc) self.validate_mandatory() self.validate_item() validate_warehouse_user(self.doc.warehouse) @@ -52,7 +48,7 @@ class DocType(DocListController): %(item_code)s at Warehouse %(warehouse)s \ as on %(posting_date)s %(posting_time)s""" % self.doc.fields) - sself.doc.fields.pop('batch_bal') + self.doc.fields.pop('batch_bal') def validate_mandatory(self): mandatory = ['warehouse','posting_date','voucher_type','voucher_no','actual_qty','company'] diff --git a/stock/utils.py b/stock/utils.py index 1f501644ffa..95b9bffc555 100644 --- a/stock/utils.py +++ b/stock/utils.py @@ -252,10 +252,10 @@ def get_buying_amount(voucher_type, voucher_no, item_row, stock_ledger_entries): def reorder_item(): """ Reorder item if stock reaches reorder level""" - if not hasattr(webnotes, "auto_indent"): - webnotes.auto_indent = cint(webnotes.conn.get_value('Stock Settings', None, 'auto_indent')) + if getattr(webnotes.local, "auto_indent", None) is None: + webnotes.local.auto_indent = cint(webnotes.conn.get_value('Stock Settings', None, 'auto_indent')) - if webnotes.auto_indent: + if webnotes.local.auto_indent: material_requests = {} bin_list = webnotes.conn.sql("""select item_code, warehouse, projected_qty from tabBin where ifnull(item_code, '') != '' and ifnull(warehouse, '') != '' @@ -340,18 +340,18 @@ def create_material_request(material_requests): mr_list.append(mr_bean) except: - if webnotes.message_log: - exceptions_list.append([] + webnotes.message_log) - webnotes.message_log = [] + if webnotes.local.message_log: + exceptions_list.append([] + webnotes.local.message_log) + webnotes.local.message_log = [] else: exceptions_list.append(webnotes.getTraceback()) if mr_list: - if not hasattr(webnotes, "reorder_email_notify"): - webnotes.reorder_email_notify = cint(webnotes.conn.get_value('Stock Settings', None, + if getattr(webnotes.local, "reorder_email_notify", None) is None: + webnotes.local.reorder_email_notify = cint(webnotes.conn.get_value('Stock Settings', None, 'reorder_email_notify')) - if(webnotes.reorder_email_notify): + if(webnotes.local.reorder_email_notify): send_email_notification(mr_list) if exceptions_list: From 915eda9c4ad2852bbb01d2970ae12baf67dce2f8 Mon Sep 17 00:00:00 2001 From: Rushabh Mehta Date: Fri, 11 Oct 2013 10:56:49 +0530 Subject: [PATCH 155/200] [minor] Added allow_rename in Employee webnotes/erpnetx#962 --- hr/doctype/employee/employee.txt | 3 ++- portal/templates/pages/cart.py | 3 ++- portal/templates/pages/profile.py | 1 + 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/hr/doctype/employee/employee.txt b/hr/doctype/employee/employee.txt index bbe87ad8801..4ed873275ab 100644 --- a/hr/doctype/employee/employee.txt +++ b/hr/doctype/employee/employee.txt @@ -2,12 +2,13 @@ { "creation": "2013-03-07 09:04:18", "docstatus": 0, - "modified": "2013-08-08 14:22:11", + "modified": "2013-10-11 10:52:53", "modified_by": "Administrator", "owner": "Administrator" }, { "allow_attach": 1, + "allow_rename": 1, "autoname": "naming_series:", "doctype": "DocType", "document_type": "Master", diff --git a/portal/templates/pages/cart.py b/portal/templates/pages/cart.py index 24b474a55c3..ecf3163f0ad 100644 --- a/portal/templates/pages/cart.py +++ b/portal/templates/pages/cart.py @@ -3,4 +3,5 @@ from __future__ import unicode_literals -no_cache = True \ No newline at end of file +no_cache = True +no_sitemap = True \ No newline at end of file diff --git a/portal/templates/pages/profile.py b/portal/templates/pages/profile.py index 3d6a86f9cc6..3a75cfb0823 100644 --- a/portal/templates/pages/profile.py +++ b/portal/templates/pages/profile.py @@ -7,6 +7,7 @@ from webnotes import _ from webnotes.utils import cstr no_cache = True +no_sitemap = True def get_context(): from selling.utils.cart import get_lead_or_customer From 56bc5c0ea68195109e4576a96a31255de11c5c03 Mon Sep 17 00:00:00 2001 From: Rushabh Mehta Date: Fri, 11 Oct 2013 14:34:46 +0530 Subject: [PATCH 156/200] [material request] Added feature to pull items from BOM --- manufacturing/doctype/bom/bom.py | 51 ++++++++++++++- manufacturing/doctype/bom/test_bom.py | 56 +++++++++++++++- stock/doctype/item/test_item.py | 27 +++++++- .../material_request/material_request.js | 53 ++++++++++++++- .../material_request_item.txt | 4 +- stock/doctype/stock_entry/stock_entry.py | 64 ++----------------- stock/doctype/stock_entry/test_stock_entry.py | 3 - 7 files changed, 188 insertions(+), 70 deletions(-) diff --git a/manufacturing/doctype/bom/bom.py b/manufacturing/doctype/bom/bom.py index 20c11410930..5954475376e 100644 --- a/manufacturing/doctype/bom/bom.py +++ b/manufacturing/doctype/bom/bom.py @@ -402,4 +402,53 @@ class DocType: if act_pbom and act_pbom[0][0]: action = self.doc.docstatus < 2 and _("deactivate") or _("cancel") msgprint(_("Cannot ") + action + _(": It is linked to other active BOM(s)"), - raise_exception=1) \ No newline at end of file + raise_exception=1) + +def get_bom_items_as_dict(bom, qty=1, fetch_exploded=1): + item_dict = {} + + query = """select + bom_item.item_code, + ifnull(sum(bom_item.qty_consumed_per_unit),0) * %(qty)s as qty, + item.description, + item.stock_uom, + item.default_warehouse + from + `tab%(table)s` bom_item, `tabItem` item + where + bom_item.docstatus < 2 + and bom_item.parent = "%(bom)s" + and item.name = bom_item.item_code + %(conditions)s + group by item_code, stock_uom""" + + if fetch_exploded: + items = webnotes.conn.sql(query % { + "qty": qty, + "table": "BOM Explosion Item", + "bom": bom, + "conditions": """and ifnull(item.is_pro_applicable, 'No') = 'No' + and ifnull(item.is_sub_contracted_item, 'No') = 'No' """ + }, as_dict=True) + else: + items = webnotes.conn.sql(query % { + "qty": qty, + "table": "BOM Item", + "bom": bom, + "conditions": "" + }, as_dict=True) + + # make unique + for item in items: + if item_dict.has_key(item.item_code): + item_dict[item.item_code]["qty"] += flt(item.qty) + else: + item_dict[item.item_code] = item + + return item_dict + +@webnotes.whitelist() +def get_bom_items(bom, qty=1, fetch_exploded=1): + items = get_bom_items_as_dict(bom, qty, fetch_exploded).values() + items.sort(lambda a, b: a.item_code > b.item_code and 1 or -1) + return items \ No newline at end of file diff --git a/manufacturing/doctype/bom/test_bom.py b/manufacturing/doctype/bom/test_bom.py index d0b394a1f89..da98faf8f40 100644 --- a/manufacturing/doctype/bom/test_bom.py +++ b/manufacturing/doctype/bom/test_bom.py @@ -7,6 +7,35 @@ import unittest import webnotes test_records = [ + [ + { + "doctype": "BOM", + "item": "_Test Item Home Desktop 100", + "quantity": 1.0, + "is_active": 1, + "is_default": 1, + "docstatus": 1 + }, + { + "doctype": "BOM Item", + "item_code": "_Test Serialized Item With Series", + "parentfield": "bom_materials", + "qty": 1.0, + "rate": 5000.0, + "amount": 5000.0, + "stock_uom": "_Test UOM" + }, + { + "doctype": "BOM Item", + "item_code": "_Test Item 2", + "parentfield": "bom_materials", + "qty": 2.0, + "rate": 1000.0, + "amount": 2000.0, + "stock_uom": "_Test UOM" + } + ], + [ { "doctype": "BOM", @@ -29,10 +58,33 @@ test_records = [ "doctype": "BOM Item", "item_code": "_Test Item Home Desktop 100", "parentfield": "bom_materials", + "bom_no": "BOM/_Test Item Home Desktop 100/001", "qty": 2.0, "rate": 1000.0, "amount": 2000.0, "stock_uom": "_Test UOM" } - ] -] \ No newline at end of file + ], +] + +class TestBOM(unittest.TestCase): + def test_get_items(self): + from manufacturing.doctype.bom.bom import get_bom_items_as_dict + items_dict = get_bom_items_as_dict(bom="BOM/_Test FG Item/001", qty=1, fetch_exploded=0) + self.assertTrue(test_records[1][1]["item_code"] in items_dict) + self.assertTrue(test_records[1][2]["item_code"] in items_dict) + self.assertEquals(len(items_dict.values()), 2) + + def test_get_items_exploded(self): + from manufacturing.doctype.bom.bom import get_bom_items_as_dict + items_dict = get_bom_items_as_dict(bom="BOM/_Test FG Item/001", qty=1, fetch_exploded=1) + self.assertTrue(test_records[1][1]["item_code"] in items_dict) + self.assertFalse(test_records[1][2]["item_code"] in items_dict) + self.assertTrue(test_records[0][1]["item_code"] in items_dict) + self.assertTrue(test_records[0][2]["item_code"] in items_dict) + self.assertEquals(len(items_dict.values()), 3) + + def test_get_items_list(self): + from manufacturing.doctype.bom.bom import get_bom_items + self.assertEquals(len(get_bom_items(bom="BOM/_Test FG Item/001", qty=1, fetch_exploded=1)), 3) + diff --git a/stock/doctype/item/test_item.py b/stock/doctype/item/test_item.py index 12bb4e05783..ad88c8cc8f7 100644 --- a/stock/doctype/item/test_item.py +++ b/stock/doctype/item/test_item.py @@ -31,7 +31,7 @@ test_records = [ "is_sales_item": "Yes", "is_service_item": "No", "inspection_required": "No", - "is_pro_applicable": "No", + "is_pro_applicable": "Yes", "is_sub_contracted_item": "No", "stock_uom": "_Test UOM", "default_income_account": "Sales - _TC", @@ -45,6 +45,26 @@ test_records = [ "material_request_type": "Purchase" }, ], + [{ + "doctype": "Item", + "item_code": "_Test Item 2", + "item_name": "_Test Item 2", + "description": "_Test Item 2", + "item_group": "_Test Item Group", + "is_stock_item": "Yes", + "is_asset_item": "No", + "has_batch_no": "No", + "has_serial_no": "No", + "is_purchase_item": "Yes", + "is_sales_item": "Yes", + "is_service_item": "No", + "inspection_required": "No", + "is_pro_applicable": "Yes", + "is_sub_contracted_item": "No", + "stock_uom": "_Test UOM", + "default_income_account": "Sales - _TC", + "default_warehouse": "_Test Warehouse - _TC", + }], [{ "doctype": "Item", "item_code": "_Test Item Home Desktop 100", @@ -61,8 +81,9 @@ test_records = [ "is_sales_item": "Yes", "is_service_item": "No", "inspection_required": "No", - "is_pro_applicable": "No", + "is_pro_applicable": "Yes", "is_sub_contracted_item": "No", + "is_manufactured_item": "Yes", "stock_uom": "_Test UOM" }, { @@ -182,7 +203,7 @@ test_records = [ "is_sales_item": "Yes", "is_service_item": "No", "inspection_required": "No", - "is_pro_applicable": "No", + "is_pro_applicable": "Yes", "is_sub_contracted_item": "No", "stock_uom": "_Test UOM" }], diff --git a/stock/doctype/material_request/material_request.js b/stock/doctype/material_request/material_request.js index 6931181dbac..99e8afb0a1a 100644 --- a/stock/doctype/material_request/material_request.js +++ b/stock/doctype/material_request/material_request.js @@ -21,7 +21,11 @@ erpnext.buying.MaterialRequestController = erpnext.buying.BuyingController.exten + wn._("Fulfilled"), cint(doc.per_ordered)); } - if(doc.docstatus == 1 && doc.status != 'Stopped'){ + if(doc.docstatus==0) { + cur_frm.add_custom_button(wn._("Get Items from BOM"), cur_frm.cscript.get_items_from_bom, "icon-sitemap"); + } + + if(doc.docstatus == 1 && doc.status != 'Stopped') { if(doc.material_request_type === "Purchase") cur_frm.add_custom_button("Make Supplier Quotation", this.make_supplier_quotation); @@ -63,6 +67,53 @@ erpnext.buying.MaterialRequestController = erpnext.buying.BuyingController.exten }, + schedule_date: function(doc, cdt, cdn) { + var val = locals[cdt][cdn].schedule_date; + if(val) { + $.each(wn.model.get("Material Request Item", { parent: cur_frm.doc.name }), function(i, d) { + if(!d.schedule_date) { + d.schedule_date = val; + } + }); + refresh_field("indent_details"); + } + }, + + get_items_from_bom: function() { + var d = new wn.ui.Dialog({ + title: wn._("Get Items from BOM"), + fields: [ + {"fieldname":"bom", "fieldtype":"Link", "label":wn._("BOM"), + options:"BOM"}, + {"fieldname":"fetch_exploded", "fieldtype":"Check", + "label":wn._("Fetch exploded BOM (including sub-assemblies)"), "default":1}, + {fieldname:"fetch", "label":wn._("Get Items from BOM"), "fieldtype":"Button"} + ] + }); + d.get_input("fetch").on("click", function() { + var values = d.get_values(); + if(!values) return; + + wn.call({ + method:"manufacturing.doctype.bom.bom.get_bom_items", + args: values, + callback: function(r) { + $.each(r.message, function(i, item) { + var d = wn.model.add_child(cur_frm.doc, "Material Request Item", "indent_details"); + d.item_code = item.item_code; + d.description = item.description; + d.warehouse = item.default_warehouse; + d.uom = item.stock_uom; + d.qty = item.qty; + }); + d.hide(); + refresh_field("indent_details"); + } + }); + }); + d.show(); + }, + tc_name: function() { this.get_terms(); }, diff --git a/stock/doctype/material_request_item/material_request_item.txt b/stock/doctype/material_request_item/material_request_item.txt index dae97e09295..2ef4acd531e 100644 --- a/stock/doctype/material_request_item/material_request_item.txt +++ b/stock/doctype/material_request_item/material_request_item.txt @@ -2,7 +2,7 @@ { "creation": "2013-02-22 01:28:02", "docstatus": 0, - "modified": "2013-08-07 14:45:11", + "modified": "2013-10-11 14:21:32", "modified_by": "Administrator", "owner": "Administrator" }, @@ -138,7 +138,7 @@ "oldfieldname": "item_name", "oldfieldtype": "Data", "print_width": "100px", - "reqd": 1, + "reqd": 0, "search_index": 1, "width": "100px" }, diff --git a/stock/doctype/stock_entry/stock_entry.py b/stock/doctype/stock_entry/stock_entry.py index 63cfd2be90f..78a0bd28126 100644 --- a/stock/doctype/stock_entry/stock_entry.py +++ b/stock/doctype/stock_entry/stock_entry.py @@ -472,68 +472,16 @@ class DocType(StockController): self.get_stock_and_rate() def get_bom_raw_materials(self, qty): - """ - get all items from flat bom except - child items of sub-contracted and sub assembly items - and sub assembly items itself. - """ + from manufacturing.doctype.bom.bom import get_bom_items_as_dict + # item dict = { item_code: {qty, description, stock_uom} } - item_dict = {} + item_dict = get_bom_items_as_dict(self.doc.bom_no, qty=qty, fetch_exploded = self.doc.use_multi_level_bom) - def _make_items_dict(items_list): - """makes dict of unique items with it's qty""" - for item in items_list: - if item_dict.has_key(item.item_code): - item_dict[item.item_code]["qty"] += flt(item.qty) - else: - item_dict[item.item_code] = { - "qty": flt(item.qty), - "description": item.description, - "stock_uom": item.stock_uom, - "from_warehouse": item.default_warehouse - } - - if self.doc.use_multi_level_bom: - # get all raw materials with sub assembly childs - fl_bom_sa_child_item = webnotes.conn.sql("""select - fb.item_code, - ifnull(sum(fb.qty_consumed_per_unit),0)*%s as qty, - fb.description, - fb.stock_uom, - it.default_warehouse - from - `tabBOM Explosion Item` fb,`tabItem` it - where - it.name = fb.item_code - and ifnull(it.is_pro_applicable, 'No') = 'No' - and ifnull(it.is_sub_contracted_item, 'No') = 'No' - and fb.docstatus < 2 - and fb.parent=%s group by item_code, stock_uom""", - (qty, self.doc.bom_no), as_dict=1) - - if fl_bom_sa_child_item: - _make_items_dict(fl_bom_sa_child_item) - else: - # get only BOM items - fl_bom_sa_items = webnotes.conn.sql("""select - `tabItem`.item_code, - ifnull(sum(`tabBOM Item`.qty_consumed_per_unit), 0) *%s as qty, - `tabItem`.description, - `tabItem`.stock_uom, - `tabItem`.default_warehouse - from - `tabBOM Item`, `tabItem` - where - `tabBOM Item`.parent = %s and - `tabBOM Item`.item_code = tabItem.name and - `tabBOM Item`.docstatus < 2 - group by item_code""", (qty, self.doc.bom_no), as_dict=1) - - if fl_bom_sa_items: - _make_items_dict(fl_bom_sa_items) + for item in item_dict.values(): + item.from_warehouse = item.default_warehouse return item_dict - + def get_pending_raw_materials(self, pro_obj): """ issue (item quantity) that is pending to issue or desire to transfer, diff --git a/stock/doctype/stock_entry/test_stock_entry.py b/stock/doctype/stock_entry/test_stock_entry.py index f01a83b2f72..4b36e5828c2 100644 --- a/stock/doctype/stock_entry/test_stock_entry.py +++ b/stock/doctype/stock_entry/test_stock_entry.py @@ -1,9 +1,6 @@ # Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. # License: GNU General Public License v3. See license.txt -# ERPNext - web based ERP (http://erpnext.com) -# For license information, please see license.txt - from __future__ import unicode_literals import webnotes, unittest from webnotes.utils import flt From 6bc48070a1c4bcda34ada8f9f262bfd3a2bced0c Mon Sep 17 00:00:00 2001 From: Anand Doshi Date: Mon, 14 Oct 2013 15:48:57 +0530 Subject: [PATCH 157/200] Moved Custom Server Scripts to custom_scripts/doctype_name.py --- .../p05_server_custom_script_to_file.py | 35 +++++++++++++++++++ patches/patch_list.py | 1 + 2 files changed, 36 insertions(+) create mode 100644 patches/october_2013/p05_server_custom_script_to_file.py diff --git a/patches/october_2013/p05_server_custom_script_to_file.py b/patches/october_2013/p05_server_custom_script_to_file.py new file mode 100644 index 00000000000..93cfa346efb --- /dev/null +++ b/patches/october_2013/p05_server_custom_script_to_file.py @@ -0,0 +1,35 @@ +# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. +# License: GNU General Public License v3. See license.txt + +from __future__ import unicode_literals +import webnotes + +def execute(): + """ + Assuming that some kind of indentation exists: + - Find indentation of server custom script + - replace indentation with tabs + - Add line: + class CustomDocType(DocType): + - Add tab indented code after this line + - Write to file + - Delete custom script record + """ + from core.doctype.custom_script.custom_script import make_custom_server_script_file + for name, dt, script in webnotes.conn.sql("""select name, dt, script from `tabCustom Script` + where script_type='Server'"""): + if script.strip(): + script = indent_using_tabs(script) + make_custom_server_script_file(dt, script) + webnotes.delete_doc("Custom Script", name) + +def indent_using_tabs(script): + for line in script.split("\n"): + try: + indentation_used = line[:line.index("def ")] + script = script.replace(indentation_used, "\t") + break + except ValueError: + pass + + return script \ No newline at end of file diff --git a/patches/patch_list.py b/patches/patch_list.py index 92dd52742ca..8a79155a512 100644 --- a/patches/patch_list.py +++ b/patches/patch_list.py @@ -225,4 +225,5 @@ patch_list = [ "patches.october_2013.p03_crm_update_status", "execute:webnotes.delete_doc('DocType', 'Setup Control')", "patches.october_2013.p04_wsgi_migration", + "patches.october_2013.p05_server_custom_script_to_file", ] \ No newline at end of file From 3510764e7c8fd03aab0b16678b846b547237c21d Mon Sep 17 00:00:00 2001 From: Anand Doshi Date: Mon, 14 Oct 2013 18:59:16 +0530 Subject: [PATCH 158/200] [minor] plugin architecture, first cut --- .../p05_server_custom_script_to_file.py | 3 ++- utilities/demo/demo_control_panel.py | 27 ++++++++++--------- utilities/demo/demo_docs/Lead.csv | 12 ++++----- utilities/demo/make_demo.py | 2 +- utilities/demo/make_erpnext_demo.py | 13 +++++---- 5 files changed, 30 insertions(+), 27 deletions(-) diff --git a/patches/october_2013/p05_server_custom_script_to_file.py b/patches/october_2013/p05_server_custom_script_to_file.py index 93cfa346efb..3a7e7702652 100644 --- a/patches/october_2013/p05_server_custom_script_to_file.py +++ b/patches/october_2013/p05_server_custom_script_to_file.py @@ -15,13 +15,14 @@ def execute(): - Write to file - Delete custom script record """ + import os + from webnotes.utils import get_site_base_path from core.doctype.custom_script.custom_script import make_custom_server_script_file for name, dt, script in webnotes.conn.sql("""select name, dt, script from `tabCustom Script` where script_type='Server'"""): if script.strip(): script = indent_using_tabs(script) make_custom_server_script_file(dt, script) - webnotes.delete_doc("Custom Script", name) def indent_using_tabs(script): for line in script.split("\n"): diff --git a/utilities/demo/demo_control_panel.py b/utilities/demo/demo_control_panel.py index 3123f41e089..694f7d1201e 100644 --- a/utilities/demo/demo_control_panel.py +++ b/utilities/demo/demo_control_panel.py @@ -1,13 +1,16 @@ +from __future__ import unicode_literals +import webnotes - def on_login(self): - from webnotes.utils import validate_email_add - from webnotes import conf - if "demo_notify_url" in conf: - if webnotes.form_dict.lead_email and validate_email_add(webnotes.form_dict.lead_email): - import requests - response = requests.post(conf.demo_notify_url, data={ - "cmd":"portal.utils.send_message", - "subject":"Logged into Demo", - "sender": webnotes.form_dict.lead_email, - "message": "via demo.erpnext.com" - }) +class CustomDocType(DocType): + def on_login(self): + from webnotes.utils import validate_email_add + from webnotes import conf + if "demo_notify_url" in conf: + if webnotes.form_dict.lead_email and validate_email_add(webnotes.form_dict.lead_email): + import requests + response = requests.post(conf.demo_notify_url, data={ + "cmd":"portal.utils.send_message", + "subject":"Logged into Demo", + "sender": webnotes.form_dict.lead_email, + "message": "via demo.erpnext.com" + }) diff --git a/utilities/demo/demo_docs/Lead.csv b/utilities/demo/demo_docs/Lead.csv index a97fe3bacb7..a7004e4810e 100644 --- a/utilities/demo/demo_docs/Lead.csv +++ b/utilities/demo/demo_docs/Lead.csv @@ -1,5 +1,5 @@ Data Import Template,,,,,,,,,,,,,,,,,,,,,,,,,, -Table:,Lead,,,,,,,,,,,,,,,,,,,,,,,,,, +Table:,Lead,,,,,,,,,,,,,,,,,,,,,,,,, ,,,,,,,,,,,,,,,,,,,,,,,,,, ,,,,,,,,,,,,,,,,,,,,,,,,,, Notes:,,,,,,,,,,,,,,,,,,,,,,,,,, @@ -11,11 +11,11 @@ Only mandatory fields are necessary for new records. You can delete non-mandator "If you are uploading new records, ""Naming Series"" becomes mandatory, if present.",,,,,,,,,,,,,,,,,,,,,,,,,, You can only upload upto 5000 records in one go. (may be less in some cases),,,,,,,,,,,,,,,,,,,,,,,,,, ,,,,,,,,,,,,,,,,,,,,,,,,,, -Column Labels,ID,Contact Name,Status,Naming Series,Company Name,Email Id,Source,From Customer,Campaign Name,Remark,Phone,Mobile No.,Fax,Website,Territory,Lead Type,Lead Owner,Market Segment,Industry,Request Type,Next Contact By,Next Contact Date,Last Contact Date,Company,Unsubscribed,Blog Subscriber -Column Name:,name,lead_name,status,naming_series,company_name,email_id,source,customer,campaign_name,remark,phone,mobile_no,fax,website,territory,type,lead_owner,market_segment,industry,request_type,contact_by,contact_date,last_contact_date,company,unsubscribed,blog_subscriber -Mandatory:,Yes,Yes,Yes,No,No,No,No,No,No,No,No,No,No,No,No,No,No,No,No,No,No,No,No,No,No,No -Type:,Data (text),Data,Select,Select,Data,Data,Select,Link,Link,Small Text,Data,Data,Data,Data,Link,Select,Link,Select,Link,Select,Link,Date,Date,Link,Check,Check -Info:,,,"Lead, Open, Replied, Opportunity, Interested, Converted, Do Not Contact","One of: LEAD, LEAD/10-11/, LEAD/MUMBAI/",,,"One of: Advertisement, Blog Post, Campaign, Call, Customer, Exhibition, Supplier, Website, Email",Valid Customer,Valid Campaign,,,,,,Valid Territory,"One of: Client, Channel Partner, Consultant",Valid Profile,"One of: Lower Income, Middle Income, Upper Income",Valid Industry Type,"One of: Product Enquiry, Request for Information, Suggestions, Other",Valid Profile,,,Valid Company,0 or 1,0 or 1 +Column Labels,ID,Contact Name,Status,Naming Series,Company Name,Email Id,Source,From Customer,Campaign Name,Remark,Phone,Mobile No.,Fax,Website,Territory,Lead Type,Lead Owner,Market Segment,Industry,Request Type,Next Contact By,Next Contact Date,Company,Unsubscribed,Blog Subscriber, +Column Name:,name,lead_name,status,naming_series,company_name,email_id,source,customer,campaign_name,remark,phone,mobile_no,fax,website,territory,type,lead_owner,market_segment,industry,request_type,contact_by,contact_date,company,unsubscribed,blog_subscriber, +Mandatory:,Yes,Yes,Yes,No,No,No,No,No,No,No,No,No,No,No,No,No,No,No,No,No,No,No,No,No,No, +Type:,Data (text),Data,Select,Select,Data,Data,Select,Link,Link,Small Text,Data,Data,Data,Data,Link,Select,Link,Select,Link,Select,Link,Date,Link,Check,Check, +Info:,,,"Lead, Open, Replied, Opportunity, Interested, Converted, Do Not Contact","One of: LEAD, LEAD/10-11/, LEAD/MUMBAI/",,,"One of: Advertisement, Blog Post, Campaign, Call, Customer, Exhibition, Supplier, Website, Email",Valid Customer,Valid Campaign,,,,,,Valid Territory,"One of: Client, Channel Partner, Consultant",Valid Profile,"One of: Lower Income, Middle Income, Upper Income",Valid Industry Type,"One of: Product Enquiry, Request for Information, Suggestions, Other",Valid Profile,,Valid Company,0 or 1,0 or 1, Start entering data below this line,,,,,,,,,,,,,,,,,,,,,,,,,, ,,Mart Lakeman,Lead,,Zany Brainy,MartLakeman@einrot.com,,,,,,,,,,,,,,,,,,,, ,,Saga Lundqvist,Lead,,Patterson-Fletcher,SagaLundqvist@dayrep.com,,,,,,,,,,,,,,,,,,,, diff --git a/utilities/demo/make_demo.py b/utilities/demo/make_demo.py index 219ce864964..9df34c26aeb 100644 --- a/utilities/demo/make_demo.py +++ b/utilities/demo/make_demo.py @@ -164,7 +164,7 @@ def run_stock(current_date): if can_make("Delivery Note"): from selling.doctype.sales_order.sales_order import make_delivery_note from stock.stock_ledger import NegativeStockError - from stock.doctype.stock_ledger_entry.stock_ledger_entry import SerialNoRequiredError, SerialNoQtyError + from stock.doctype.serial_no.serial_no import SerialNoRequiredError, SerialNoQtyError report = "Ordered Items To Be Delivered" for so in list(set([r[0] for r in query_report.run(report)["result"] if r[0]!="Total"]))[:how_many("Delivery Note")]: dn = webnotes.bean(make_delivery_note(so)) diff --git a/utilities/demo/make_erpnext_demo.py b/utilities/demo/make_erpnext_demo.py index 262a7595c22..cda38d690dc 100644 --- a/utilities/demo/make_erpnext_demo.py +++ b/utilities/demo/make_erpnext_demo.py @@ -105,13 +105,12 @@ def make_demo_login_page(): webnotes.conn.commit() def make_demo_on_login_script(): - webnotes.conn.sql("""delete from `tabCustom Script` where dt='Control Panel'""") - s = webnotes.new_bean("Custom Script") - s.doc.dt = "Control Panel" - s.doc.script_type = "Server" - with open(os.path.join(os.path.dirname(__file__), "demo_control_panel.py"), "r") as dfile: - s.doc.script = dfile.read() - s.insert() + import shutil + from core.doctype.custom_script.custom_script import get_custom_server_script_path + custom_script_path = get_custom_server_script_path("Control Panel") + webnotes.create_folder(os.path.dirname(custom_script_path)) + + shutil.copyfile(os.path.join(os.path.dirname(__file__), "demo_control_panel.py"), custom_script_path) cp = webnotes.bean("Control Panel") cp.doc.custom_startup_code = """wn.ui.toolbar.show_banner('You are using ERPNext Demo. To start your own ERPNext Trial, click here')""" From c4e70c38b667111d3dfe0280844e19b54187aa8c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A1rbara=20Perretti?= Date: Mon, 14 Oct 2013 16:58:14 -0300 Subject: [PATCH 159/200] Fix translate Startup.js --- public/js/startup.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/public/js/startup.js b/public/js/startup.js index 4b58c4cadbd..3853ff11cda 100644 --- a/public/js/startup.js +++ b/public/js/startup.js @@ -41,7 +41,7 @@ erpnext.startup.show_expiry_banner = function() { var msg = ""; if (0 <= diff && diff <= 10) { var expiry_string = diff==0 ? "today" : repl("in %(diff)s day(s)", { diff: diff }); - msg = repl(wn._('Your ERPNext subscription will expire %(expiry_string)s. %(payment_link)s')), + msg = repl(wn._('Your ERPNext subscription will expire %(expiry_string)s. %(payment_link)s'), { expiry_string: expiry_string, payment_link: payment_link }); } else if (diff < 0) { msg = repl(wn._('This ERPNext subscription has expired. %(payment_link)s'), {payment_link: payment_link}); From f0feb73dedd4c6bd124a40eb1a8694d874c37ed0 Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Tue, 15 Oct 2013 12:22:41 +0530 Subject: [PATCH 160/200] [minor] bypass plugin field related operational error --- patches/patch_list.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/patches/patch_list.py b/patches/patch_list.py index 8a79155a512..266a01fef84 100644 --- a/patches/patch_list.py +++ b/patches/patch_list.py @@ -3,10 +3,8 @@ from __future__ import unicode_literals patch_list = [ - "execute:webnotes.reload_doc('core', 'doctype', 'doctype', force=True) #2013-07-15", - "execute:webnotes.reload_doc('core', 'doctype', 'docfield', force=True) #2013-07-15", - "execute:webnotes.reload_doc('core', 'doctype', 'doctype', force=True) #2013-07-16", - "execute:webnotes.reload_doc('core', 'doctype', 'docfield', force=True) #2013-07-16", + "execute:webnotes.reload_doc('core', 'doctype', 'doctype', force=True) #2013-10-15", + "execute:webnotes.reload_doc('core', 'doctype', 'docfield', force=True) #2013-10-15", "execute:webnotes.reload_doc('core', 'doctype', 'docperm') #2013-07-16", "execute:webnotes.reload_doc('core', 'doctype', 'page') #2013-07-16", "execute:webnotes.reload_doc('core', 'doctype', 'report') #2013-07-16", From a295bf54214ced9cad2490a562b48409a9a83ebe Mon Sep 17 00:00:00 2001 From: Anand Doshi Date: Tue, 15 Oct 2013 19:52:29 +0530 Subject: [PATCH 161/200] [minor] don't rollback when running all tests, fixed test cases --- .../test_period_closing_voucher.py | 3 ++ .../purchase_invoice/purchase_invoice.py | 2 +- .../test_leave_application.py | 9 ++-- .../leave_block_list/test_leave_block_list.py | 3 ++ manufacturing/doctype/bom/bom.py | 1 + manufacturing/doctype/bom/test_bom.py | 47 +++++++++++++++---- .../time_log_batch/test_time_log_batch.py | 26 ++++++++-- selling/doctype/customer/test_customer.py | 5 ++ selling/doctype/quotation/test_quotation.py | 10 ++-- .../doctype/sales_order/test_sales_order.py | 9 ++-- .../delivery_note/test_delivery_note.py | 28 ++++++----- stock/doctype/item/test_item.py | 46 +++++++++++++++++- support/doctype/newsletter/newsletter.py | 7 ++- support/doctype/newsletter/test_newsletter.py | 9 ++-- utilities/demo/make_demo.py | 2 +- 15 files changed, 160 insertions(+), 47 deletions(-) diff --git a/accounts/doctype/period_closing_voucher/test_period_closing_voucher.py b/accounts/doctype/period_closing_voucher/test_period_closing_voucher.py index c21d63f6ecb..b9ac8bd740c 100644 --- a/accounts/doctype/period_closing_voucher/test_period_closing_voucher.py +++ b/accounts/doctype/period_closing_voucher/test_period_closing_voucher.py @@ -8,6 +8,9 @@ import webnotes class TestPeriodClosingVoucher(unittest.TestCase): def test_closing_entry(self): + # clear GL Entries + webnotes.conn.sql("""delete from `tabGL Entry`""") + from accounts.doctype.journal_voucher.test_journal_voucher import test_records as jv_records jv = webnotes.bean(copy=jv_records[2]) jv.insert() diff --git a/accounts/doctype/purchase_invoice/purchase_invoice.py b/accounts/doctype/purchase_invoice/purchase_invoice.py index a562c67a38a..c65b9acb2b9 100644 --- a/accounts/doctype/purchase_invoice/purchase_invoice.py +++ b/accounts/doctype/purchase_invoice/purchase_invoice.py @@ -434,7 +434,7 @@ class DocType(BuyingController): def update_raw_material_cost(self): if self.sub_contracted_items: for d in self.doclist.get({"parentfield": "entries"}): - rm_cost = webnotes.conn.sql(""" select raw_material_cost / quantity + rm_cost = webnotes.conn.sql("""select raw_material_cost / quantity from `tabBOM` where item = %s and is_default = 1 and docstatus = 1 and is_active = 1 """, (d.item_code,)) rm_cost = rm_cost and flt(rm_cost[0][0]) or 0 diff --git a/hr/doctype/leave_application/test_leave_application.py b/hr/doctype/leave_application/test_leave_application.py index c89f7c4537c..7a900e3bfee 100644 --- a/hr/doctype/leave_application/test_leave_application.py +++ b/hr/doctype/leave_application/test_leave_application.py @@ -7,6 +7,9 @@ import unittest from hr.doctype.leave_application.leave_application import LeaveDayBlockedError, OverlapError class TestLeaveApplication(unittest.TestCase): + def tearDown(self): + webnotes.session.user = "Administrator" + def _clear_roles(self): webnotes.conn.sql("""delete from `tabUserRole` where parent in ("test@example.com", "test1@example.com", "test2@example.com")""") @@ -15,6 +18,7 @@ class TestLeaveApplication(unittest.TestCase): webnotes.conn.sql("""delete from `tabLeave Application`""") def _add_employee_leave_approver(self, employee, leave_approver): + temp_session_user = webnotes.session.user webnotes.session.user = "Administrator" employee = webnotes.bean("Employee", employee) employee.doclist.append({ @@ -23,6 +27,7 @@ class TestLeaveApplication(unittest.TestCase): "leave_approver": leave_approver }) employee.save() + webnotes.session.user = temp_session_user def get_application(self, doclist): application = webnotes.bean(copy=doclist) @@ -31,7 +36,6 @@ class TestLeaveApplication(unittest.TestCase): return application def test_block_list(self): - webnotes.session.user = "Administrator" self._clear_roles() from webnotes.profile import add_role @@ -54,7 +58,6 @@ class TestLeaveApplication(unittest.TestCase): self.assertTrue(application.insert()) def test_overlap(self): - webnotes.session.user = "Administrator" self._clear_roles() self._clear_applications() @@ -72,7 +75,6 @@ class TestLeaveApplication(unittest.TestCase): self.assertRaises(OverlapError, application.insert) def test_global_block_list(self): - webnotes.session.user = "Administrator" self._clear_roles() from webnotes.profile import add_role @@ -98,7 +100,6 @@ class TestLeaveApplication(unittest.TestCase): "applies_to_all_departments", 0) def test_leave_approval(self): - webnotes.session.user = "Administrator" self._clear_roles() from webnotes.profile import add_role diff --git a/hr/doctype/leave_block_list/test_leave_block_list.py b/hr/doctype/leave_block_list/test_leave_block_list.py index e266cd84d67..34814d9380b 100644 --- a/hr/doctype/leave_block_list/test_leave_block_list.py +++ b/hr/doctype/leave_block_list/test_leave_block_list.py @@ -7,6 +7,9 @@ import unittest from hr.doctype.leave_block_list.leave_block_list import get_applicable_block_dates class TestLeaveBlockList(unittest.TestCase): + def tearDown(self): + webnotes.session.user = "Administrator" + def test_get_applicable_block_dates(self): webnotes.session.user = "test@example.com" webnotes.conn.set_value("Department", "_Test Department", "leave_block_list", diff --git a/manufacturing/doctype/bom/bom.py b/manufacturing/doctype/bom/bom.py index 5954475376e..97a2f96c6e0 100644 --- a/manufacturing/doctype/bom/bom.py +++ b/manufacturing/doctype/bom/bom.py @@ -332,6 +332,7 @@ class DocType: d.amount = flt(d.rate) * flt(d.qty) d.qty_consumed_per_unit = flt(d.qty) / flt(self.doc.quantity) total_rm_cost += d.amount + self.doc.raw_material_cost = total_rm_cost def update_exploded_items(self): diff --git a/manufacturing/doctype/bom/test_bom.py b/manufacturing/doctype/bom/test_bom.py index da98faf8f40..2f4424eb978 100644 --- a/manufacturing/doctype/bom/test_bom.py +++ b/manufacturing/doctype/bom/test_bom.py @@ -10,7 +10,7 @@ test_records = [ [ { "doctype": "BOM", - "item": "_Test Item Home Desktop 100", + "item": "_Test Item Home Desktop Manufactured", "quantity": 1.0, "is_active": 1, "is_default": 1, @@ -58,7 +58,36 @@ test_records = [ "doctype": "BOM Item", "item_code": "_Test Item Home Desktop 100", "parentfield": "bom_materials", - "bom_no": "BOM/_Test Item Home Desktop 100/001", + "qty": 2.0, + "rate": 1000.0, + "amount": 2000.0, + "stock_uom": "_Test UOM" + } + ], + + [ + { + "doctype": "BOM", + "item": "_Test FG Item 2", + "quantity": 1.0, + "is_active": 1, + "is_default": 1, + "docstatus": 1 + }, + { + "doctype": "BOM Item", + "item_code": "_Test Item", + "parentfield": "bom_materials", + "qty": 1.0, + "rate": 5000.0, + "amount": 5000.0, + "stock_uom": "_Test UOM" + }, + { + "doctype": "BOM Item", + "item_code": "_Test Item Home Desktop Manufactured", + "bom_no": "BOM/_Test Item Home Desktop Manufactured/001", + "parentfield": "bom_materials", "qty": 2.0, "rate": 1000.0, "amount": 2000.0, @@ -70,21 +99,21 @@ test_records = [ class TestBOM(unittest.TestCase): def test_get_items(self): from manufacturing.doctype.bom.bom import get_bom_items_as_dict - items_dict = get_bom_items_as_dict(bom="BOM/_Test FG Item/001", qty=1, fetch_exploded=0) - self.assertTrue(test_records[1][1]["item_code"] in items_dict) - self.assertTrue(test_records[1][2]["item_code"] in items_dict) + items_dict = get_bom_items_as_dict(bom="BOM/_Test FG Item 2/001", qty=1, fetch_exploded=0) + self.assertTrue(test_records[2][1]["item_code"] in items_dict) + self.assertTrue(test_records[2][2]["item_code"] in items_dict) self.assertEquals(len(items_dict.values()), 2) def test_get_items_exploded(self): from manufacturing.doctype.bom.bom import get_bom_items_as_dict - items_dict = get_bom_items_as_dict(bom="BOM/_Test FG Item/001", qty=1, fetch_exploded=1) - self.assertTrue(test_records[1][1]["item_code"] in items_dict) - self.assertFalse(test_records[1][2]["item_code"] in items_dict) + items_dict = get_bom_items_as_dict(bom="BOM/_Test FG Item 2/001", qty=1, fetch_exploded=1) + self.assertTrue(test_records[2][1]["item_code"] in items_dict) + self.assertFalse(test_records[2][2]["item_code"] in items_dict) self.assertTrue(test_records[0][1]["item_code"] in items_dict) self.assertTrue(test_records[0][2]["item_code"] in items_dict) self.assertEquals(len(items_dict.values()), 3) def test_get_items_list(self): from manufacturing.doctype.bom.bom import get_bom_items - self.assertEquals(len(get_bom_items(bom="BOM/_Test FG Item/001", qty=1, fetch_exploded=1)), 3) + self.assertEquals(len(get_bom_items(bom="BOM/_Test FG Item 2/001", qty=1, fetch_exploded=1)), 3) diff --git a/projects/doctype/time_log_batch/test_time_log_batch.py b/projects/doctype/time_log_batch/test_time_log_batch.py index 34a0cc06c9f..4976dfe46da 100644 --- a/projects/doctype/time_log_batch/test_time_log_batch.py +++ b/projects/doctype/time_log_batch/test_time_log_batch.py @@ -5,15 +5,31 @@ import webnotes, unittest class TimeLogBatchTest(unittest.TestCase): def test_time_log_status(self): - self.assertEquals(webnotes.conn.get_value("Time Log", "_T-Time Log-00001", "status"), "Submitted") - tlb = webnotes.bean("Time Log Batch", "_T-Time Log Batch-00001") + from projects.doctype.time_log.test_time_log import test_records as time_log_records + time_log = webnotes.bean(copy=time_log_records[0]) + time_log.doc.fields.update({ + "from_time": "2013-01-02 10:00:00", + "to_time": "2013-01-02 11:00:00", + "docstatus": 0 + }) + time_log.insert() + time_log.submit() + + self.assertEquals(webnotes.conn.get_value("Time Log", time_log.doc.name, "status"), "Submitted") + tlb = webnotes.bean(copy=test_records[0]) + tlb.doclist[1].time_log = time_log.doc.name + tlb.insert() tlb.submit() - self.assertEquals(webnotes.conn.get_value("Time Log", "_T-Time Log-00001", "status"), "Batched for Billing") + + self.assertEquals(webnotes.conn.get_value("Time Log", time_log.doc.name, "status"), "Batched for Billing") tlb.cancel() - self.assertEquals(webnotes.conn.get_value("Time Log", "_T-Time Log-00001", "status"), "Submitted") + self.assertEquals(webnotes.conn.get_value("Time Log", time_log.doc.name, "status"), "Submitted") test_records = [[ - {"rate": "500"}, + { + "doctype": "Time Log Batch", + "rate": "500" + }, { "doctype": "Time Log Batch Detail", "parenttype": "Time Log Batch", diff --git a/selling/doctype/customer/test_customer.py b/selling/doctype/customer/test_customer.py index 7c90f6a1a8f..adc5a549ef9 100644 --- a/selling/doctype/customer/test_customer.py +++ b/selling/doctype/customer/test_customer.py @@ -17,6 +17,8 @@ class TestCustomer(unittest.TestCase): (("_Test Customer 1 Renamed",),)) self.assertEqual(webnotes.conn.exists("Customer", "_Test Customer 1"), ()) + webnotes.rename_doc("Customer", "_Test Customer 1 Renamed", "_Test Customer 1") + def test_merge(self): from webnotes.test_runner import make_test_records make_test_records("Sales Invoice") @@ -57,6 +59,9 @@ class TestCustomer(unittest.TestCase): # check that old name doesn't exist self.assertEqual(webnotes.conn.exists("Customer", "_Test Customer"), ()) self.assertEqual(webnotes.conn.exists("Account", "_Test Customer - _TC"), ()) + + # create back _Test Customer + webnotes.bean(copy=test_records[0]).insert() test_ignore = ["Price List"] diff --git a/selling/doctype/quotation/test_quotation.py b/selling/doctype/quotation/test_quotation.py index cf3881d0c3f..366035ef1a5 100644 --- a/selling/doctype/quotation/test_quotation.py +++ b/selling/doctype/quotation/test_quotation.py @@ -11,17 +11,19 @@ class TestQuotation(unittest.TestCase): def test_make_sales_order(self): from selling.doctype.quotation.quotation import make_sales_order - self.assertRaises(webnotes.ValidationError, make_sales_order, "_T-Quotation-00001") + quotation = webnotes.bean(copy=test_records[0]) + quotation.insert() + + self.assertRaises(webnotes.ValidationError, make_sales_order, quotation.doc.name) - quotation = webnotes.bean("Quotation","_T-Quotation-00001") quotation.submit() - sales_order = make_sales_order("_T-Quotation-00001") + sales_order = make_sales_order(quotation.doc.name) self.assertEquals(sales_order[0]["doctype"], "Sales Order") self.assertEquals(len(sales_order), 2) self.assertEquals(sales_order[1]["doctype"], "Sales Order Item") - self.assertEquals(sales_order[1]["prevdoc_docname"], "_T-Quotation-00001") + self.assertEquals(sales_order[1]["prevdoc_docname"], quotation.doc.name) self.assertEquals(sales_order[0]["customer"], "_Test Customer") sales_order[0]["delivery_date"] = "2014-01-01" diff --git a/selling/doctype/sales_order/test_sales_order.py b/selling/doctype/sales_order/test_sales_order.py index 8bd759a77da..0ee58a7fd27 100644 --- a/selling/doctype/sales_order/test_sales_order.py +++ b/selling/doctype/sales_order/test_sales_order.py @@ -72,6 +72,10 @@ class TestSalesOrder(unittest.TestCase): def create_dn_against_so(self, so, delivered_qty=0): from stock.doctype.delivery_note.test_delivery_note import test_records as dn_test_records + from stock.doctype.delivery_note.test_delivery_note import _insert_purchase_receipt + + _insert_purchase_receipt(so.doclist[1].item_code) + dn = webnotes.bean(webnotes.copy_doclist(dn_test_records[0])) dn.doclist[1].item_code = so.doclist[1].item_code dn.doclist[1].against_sales_order = so.doc.name @@ -272,14 +276,13 @@ class TestSalesOrder(unittest.TestCase): so.doclist[1].reserved_warehouse, 20.0) def test_warehouse_user(self): - webnotes.session.user = "test@example.com" - webnotes.bean("Profile", "test@example.com").get_controller()\ .add_roles("Sales User", "Sales Manager", "Material User", "Material Manager") webnotes.bean("Profile", "test2@example.com").get_controller()\ .add_roles("Sales User", "Sales Manager", "Material User", "Material Manager") - + + webnotes.session.user = "test@example.com" from stock.utils import UserNotAllowedForWarehouse so = webnotes.bean(copy = test_records[0]) diff --git a/stock/doctype/delivery_note/test_delivery_note.py b/stock/doctype/delivery_note/test_delivery_note.py index ca95a506026..2c4308bb425 100644 --- a/stock/doctype/delivery_note/test_delivery_note.py +++ b/stock/doctype/delivery_note/test_delivery_note.py @@ -9,20 +9,22 @@ import webnotes.defaults from webnotes.utils import cint from stock.doctype.purchase_receipt.test_purchase_receipt import get_gl_entries, set_perpetual_inventory, test_records as pr_test_records +def _insert_purchase_receipt(item_code=None): + if not item_code: + item_code = pr_test_records[0][1]["item_code"] + + pr = webnotes.bean(copy=pr_test_records[0]) + pr.doclist[1].item_code = item_code + pr.insert() + pr.submit() + class TestDeliveryNote(unittest.TestCase): - def _insert_purchase_receipt(self, item_code=None): - pr = webnotes.bean(copy=pr_test_records[0]) - if item_code: - pr.doclist[1].item_code = item_code - pr.insert() - pr.submit() - def test_over_billing_against_dn(self): self.clear_stock_account_balance() - self._insert_purchase_receipt() + _insert_purchase_receipt() from stock.doctype.delivery_note.delivery_note import make_sales_invoice - self._insert_purchase_receipt() + _insert_purchase_receipt() dn = webnotes.bean(copy=test_records[0]).insert() self.assertRaises(webnotes.ValidationError, make_sales_invoice, @@ -44,7 +46,7 @@ class TestDeliveryNote(unittest.TestCase): set_perpetual_inventory(0) self.assertEqual(cint(webnotes.defaults.get_global_default("auto_accounting_for_stock")), 0) - self._insert_purchase_receipt() + _insert_purchase_receipt() dn = webnotes.bean(copy=test_records[0]) dn.insert() @@ -69,7 +71,7 @@ class TestDeliveryNote(unittest.TestCase): self.assertEqual(cint(webnotes.defaults.get_global_default("auto_accounting_for_stock")), 1) webnotes.conn.set_value("Item", "_Test Item", "valuation_method", "FIFO") - self._insert_purchase_receipt() + _insert_purchase_receipt() dn = webnotes.bean(copy=test_records[0]) dn.doclist[1].expense_account = "Cost of Goods Sold - _TC" @@ -123,8 +125,8 @@ class TestDeliveryNote(unittest.TestCase): self.clear_stock_account_balance() set_perpetual_inventory() - self._insert_purchase_receipt() - self._insert_purchase_receipt("_Test Item Home Desktop 100") + _insert_purchase_receipt() + _insert_purchase_receipt("_Test Item Home Desktop 100") dn = webnotes.bean(copy=test_records[0]) dn.doclist[1].item_code = "_Test Sales BOM Item" diff --git a/stock/doctype/item/test_item.py b/stock/doctype/item/test_item.py index ad88c8cc8f7..c8930abc978 100644 --- a/stock/doctype/item/test_item.py +++ b/stock/doctype/item/test_item.py @@ -81,9 +81,9 @@ test_records = [ "is_sales_item": "Yes", "is_service_item": "No", "inspection_required": "No", - "is_pro_applicable": "Yes", + "is_pro_applicable": "No", "is_sub_contracted_item": "No", - "is_manufactured_item": "Yes", + "is_manufactured_item": "No", "stock_uom": "_Test UOM" }, { @@ -109,6 +109,7 @@ test_records = [ "inspection_required": "No", "is_pro_applicable": "No", "is_sub_contracted_item": "No", + "is_manufactured_item": "No", "stock_uom": "_Test UOM" }], [{ @@ -207,4 +208,45 @@ test_records = [ "is_sub_contracted_item": "No", "stock_uom": "_Test UOM" }], + [{ + "doctype": "Item", + "item_code": "_Test Item Home Desktop Manufactured", + "item_name": "_Test Item Home Desktop Manufactured", + "description": "_Test Item Home Desktop Manufactured", + "item_group": "_Test Item Group Desktops", + "default_warehouse": "_Test Warehouse - _TC", + "default_income_account": "Sales - _TC", + "is_stock_item": "Yes", + "is_asset_item": "No", + "has_batch_no": "No", + "has_serial_no": "No", + "is_purchase_item": "Yes", + "is_sales_item": "Yes", + "is_service_item": "No", + "inspection_required": "No", + "is_pro_applicable": "Yes", + "is_sub_contracted_item": "No", + "is_manufactured_item": "Yes", + "stock_uom": "_Test UOM" + }], + [{ + "doctype": "Item", + "item_code": "_Test FG Item 2", + "item_name": "_Test FG Item 2", + "description": "_Test FG Item 2", + "item_group": "_Test Item Group Desktops", + "is_stock_item": "Yes", + "default_warehouse": "_Test Warehouse - _TC", + "default_income_account": "Sales - _TC", + "is_asset_item": "No", + "has_batch_no": "No", + "has_serial_no": "No", + "is_purchase_item": "Yes", + "is_sales_item": "Yes", + "is_service_item": "No", + "inspection_required": "No", + "is_pro_applicable": "Yes", + "is_sub_contracted_item": "Yes", + "stock_uom": "_Test UOM" + }], ] \ No newline at end of file diff --git a/support/doctype/newsletter/newsletter.py b/support/doctype/newsletter/newsletter.py index a6b5aa29e8a..8e45768b353 100644 --- a/support/doctype/newsletter/newsletter.py +++ b/support/doctype/newsletter/newsletter.py @@ -76,14 +76,17 @@ class DocType(): sender = self.doc.send_from or webnotes.utils.get_formatted_email(self.doc.owner) from webnotes.utils.email_lib.bulk import send - webnotes.conn.auto_commit_on_many_writes = True + + if not webnotes.flags.in_test: + webnotes.conn.auto_commit_on_many_writes = True send(recipients = self.recipients, sender = sender, subject = self.doc.subject, message = self.doc.message, doctype = self.send_to_doctype, email_field = "email_id", ref_doctype = self.doc.doctype, ref_docname = self.doc.name) - webnotes.conn.auto_commit_on_many_writes = False + if not webnotes.flags.in_test: + webnotes.conn.auto_commit_on_many_writes = False def validate_send(self): if self.doc.fields.get("__islocal"): diff --git a/support/doctype/newsletter/test_newsletter.py b/support/doctype/newsletter/test_newsletter.py index fae3e40c49b..3f4e021bb36 100644 --- a/support/doctype/newsletter/test_newsletter.py +++ b/support/doctype/newsletter/test_newsletter.py @@ -45,20 +45,23 @@ test_records =[ "subject": "_Test Newsletter to Lead", "send_to_type": "Lead", "lead_source": "All", - "message": "This is a test newsletter" + "message": "This is a test newsletter", + "send_from": "admin@example.com" }], [{ "doctype": "Newsletter", "subject": "_Test Newsletter to Contact", "send_to_type": "Contact", "contact_type": "Customer", - "message": "This is a test newsletter" + "message": "This is a test newsletter", + "send_from": "admin@example.com" }], [{ "doctype": "Newsletter", "subject": "_Test Newsletter to Custom", "send_to_type": "Custom", "email_list": "test_custom@example.com, test_custom1@example.com, test_custom2@example.com", - "message": "This is a test newsletter" + "message": "This is a test newsletter", + "send_from": "admin@example.com" }], ] diff --git a/utilities/demo/make_demo.py b/utilities/demo/make_demo.py index 9df34c26aeb..21da30b9787 100644 --- a/utilities/demo/make_demo.py +++ b/utilities/demo/make_demo.py @@ -426,7 +426,7 @@ def import_data(dt, submit=False, overwrite=False): for doctype in dt: print "Importing", doctype.replace("_", " "), "..." - webnotes.form_dict = webnotes._dict() + webnotes.local.form_dict = webnotes._dict() if submit: webnotes.form_dict["params"] = json.dumps({"_submit": 1}) webnotes.uploaded_file = os.path.join(os.path.dirname(__file__), "demo_docs", doctype+".csv") From 8bf1374abf239ec5e9811eab9861ecb32d3c0cd9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A1rbara=20Perretti?= Date: Tue, 15 Oct 2013 15:22:20 -0300 Subject: [PATCH 162/200] Fix translate accounts/page/accounts_home/accounts_home.js --- accounts/page/accounts_home/accounts_home.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/accounts/page/accounts_home/accounts_home.js b/accounts/page/accounts_home/accounts_home.js index daf0206f652..7a4f511a8b4 100644 --- a/accounts/page/accounts_home/accounts_home.js +++ b/accounts/page/accounts_home/accounts_home.js @@ -88,12 +88,12 @@ wn.module_page["Accounts"] = [ { "label": wn._("Period Closing Voucher"), "doctype": "Period Closing Voucher", - description: "Close Balance Sheet and book Profit or Loss." + description: wn._("Close Balance Sheet and book Profit or Loss.") }, { "page":"voucher-import-tool", "label": wn._("Voucher Import Tool"), - "description": "Import accounting entries from CSV." + "description": wn._("Import accounting entries from CSV.") }, ] }, @@ -105,7 +105,7 @@ wn.module_page["Accounts"] = [ "label": wn._("Accounts Settings"), "route": "Form/Accounts Settings", "doctype":"Accounts Settings", - "description": "Settings for Accounts" + "description": wn._("Settings for Accounts") }, { "label": wn._("Sales Taxes and Charges Master"), @@ -150,7 +150,7 @@ wn.module_page["Accounts"] = [ { "doctype":"C-Form", "label": wn._("C-Form"), - description: "C-Form records", + description: wn._("C-Form records"), country: "India" } ] From f941e7499f7b8322de5e5ec227e5d76f02eef6a1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A1rbara=20Perretti?= Date: Tue, 15 Oct 2013 15:22:53 -0300 Subject: [PATCH 163/200] Fix translate selling/doctype/lead/lead.js --- selling/doctype/lead/lead.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/selling/doctype/lead/lead.js b/selling/doctype/lead/lead.js index 28507fb326e..8f5057d2853 100644 --- a/selling/doctype/lead/lead.js +++ b/selling/doctype/lead/lead.js @@ -24,8 +24,8 @@ erpnext.LeadController = wn.ui.form.Controller.extend({ if(in_list(user_roles,'System Manager')) { cur_frm.footer.help_area.innerHTML = '
    \ -

    Sales Email Settings
    \ - Automatically extract Leads from a mail box e.g. "sales@example.com"

    '; +

    '+wn._('Sales Email Settings')+'
    \ + '+wn._('Automatically extract Leads from a mail box e.g.')+' "sales@example.com"

    '; } }, @@ -68,7 +68,7 @@ erpnext.LeadController = wn.ui.form.Controller.extend({ order by is_primary_address, is_shipping_address desc' }, as_dict: 1, - no_results_message: 'No addresses created', + no_results_message: wn._('No addresses created'), render_row: this.render_address_row, }); // note: render_address_row is defined in contact_control.js From 1e7685e8ae67ca602221d22dd2a657cab0a4e8da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A1rbara=20Perretti?= Date: Tue, 15 Oct 2013 15:32:13 -0300 Subject: [PATCH 164/200] Fix translate accounts/page/financial_analytics/financial_analytics.js --- accounts/page/financial_analytics/financial_analytics.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/accounts/page/financial_analytics/financial_analytics.js b/accounts/page/financial_analytics/financial_analytics.js index 7a84dc7aefa..ffe29ac1a20 100644 --- a/accounts/page/financial_analytics/financial_analytics.js +++ b/accounts/page/financial_analytics/financial_analytics.js @@ -44,11 +44,11 @@ erpnext.FinancialAnalytics = erpnext.AccountTreeGrid.extend({ ], setup_columns: function() { var std_columns = [ - {id: "check", name: "Plot", field: "check", width: 30, + {id: "check", name: wn._("Plot"), field: "check", width: 30, formatter: this.check_formatter}, - {id: "name", name: "Account", field: "name", width: 300, + {id: "name", name: wn._("Account"), field: "name", width: 300, formatter: this.tree_formatter}, - {id: "opening", name: "Opening", field: "opening", hidden: true, + {id: "opening", name: wn._("Opening"), field: "opening", hidden: true, formatter: this.currency_formatter} ]; From ac0e261eee897a845ec82406d60dd9f7b21e35e5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A1rbara=20Perretti?= Date: Tue, 15 Oct 2013 15:33:54 -0300 Subject: [PATCH 165/200] Fix translate accounts/page/financial_statements/financial_statements.js --- accounts/page/financial_statements/financial_statements.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/accounts/page/financial_statements/financial_statements.js b/accounts/page/financial_statements/financial_statements.js index 6ea2c7d3297..6a116830700 100644 --- a/accounts/page/financial_statements/financial_statements.js +++ b/accounts/page/financial_statements/financial_statements.js @@ -34,11 +34,11 @@ pscript['onload_Financial Statements'] = function(wrapper) { options: ['Loading...'] }) - wrapper.appframe.add_button("Create", function() { + wrapper.appframe.add_button(wn._("Create"), function() { pscript.stmt_new(); }, "icon-refresh") - wrapper.appframe.add_button("Print", function() { + wrapper.appframe.add_button(wn._("Print"), function() { _p.go($i('print_html').innerHTML); }, "icon-print") From 32af5cd62e01279f4be28c46d05bfc3b62c12294 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A1rbara=20Perretti?= Date: Tue, 15 Oct 2013 15:52:57 -0300 Subject: [PATCH 166/200] Fix translate accounts/page/general_ledger/general_ledger.js --- accounts/page/general_ledger/general_ledger.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/accounts/page/general_ledger/general_ledger.js b/accounts/page/general_ledger/general_ledger.js index 25cf8406454..93a23889bf0 100644 --- a/accounts/page/general_ledger/general_ledger.js +++ b/accounts/page/general_ledger/general_ledger.js @@ -237,7 +237,7 @@ erpnext.GeneralLedger = wn.views.GridReport.extend({ closing.credit = opening.credit + totals.credit; if(me.account) { - me.appframe.set_title("General Ledger: " + me.account); + me.appframe.set_title(wn._("General Ledger: ") + me.account); // group by ledgers if(this.account_by_name[this.account].group_or_ledger==="Group" @@ -255,7 +255,7 @@ erpnext.GeneralLedger = wn.views.GridReport.extend({ out = [opening].concat(out).concat([totals, closing]); } else { - me.appframe.set_title("General Ledger"); + me.appframe.set_title(wn._("General Ledger")); out = out.concat([totals]); } From 54db11c3235d14109a54392cfb532dd4728a210a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A1rbara=20Perretti?= Date: Tue, 15 Oct 2013 16:06:39 -0300 Subject: [PATCH 167/200] Fix translate buying/doctype/supplier_quotation/supplier_quotation.js --- buying/doctype/supplier_quotation/supplier_quotation.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/buying/doctype/supplier_quotation/supplier_quotation.js b/buying/doctype/supplier_quotation/supplier_quotation.js index cd6127d2355..ccb903e5999 100644 --- a/buying/doctype/supplier_quotation/supplier_quotation.js +++ b/buying/doctype/supplier_quotation/supplier_quotation.js @@ -15,7 +15,7 @@ erpnext.buying.SupplierQuotationController = erpnext.buying.BuyingController.ext this._super(); if (this.frm.doc.docstatus === 1) { - cur_frm.add_custom_button("Make Purchase Order", this.make_purchase_order); + cur_frm.add_custom_button(wn._("Make Purchase Order"), this.make_purchase_order); } else if (this.frm.doc.docstatus===0) { cur_frm.add_custom_button(wn._('From Material Request'), From b0e466d55cc91fd9baf975b2a9a5b82f212b1557 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A1rbara=20Perretti?= Date: Tue, 15 Oct 2013 16:11:34 -0300 Subject: [PATCH 168/200] Fix translate buying/page/buying_home/buying_home.js --- buying/page/buying_home/buying_home.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/buying/page/buying_home/buying_home.js b/buying/page/buying_home/buying_home.js index 5db57f4f02b..1e08a3bbf33 100644 --- a/buying/page/buying_home/buying_home.js +++ b/buying/page/buying_home/buying_home.js @@ -58,7 +58,7 @@ wn.module_page["Buying"] = [ "label": wn._("Buying Settings"), "route": "Form/Buying Settings", "doctype":"Buying Settings", - "description": "Settings for Buying Module" + "description": wn._("Settings for Buying Module") }, { "label": wn._("Purchase Taxes and Charges Master"), From 21fc1f26529de5af8a202da34fe46c7b3a25ceaf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A1rbara=20Perretti?= Date: Tue, 15 Oct 2013 16:18:18 -0300 Subject: [PATCH 169/200] Fix translate buying/page/purchase_analytics/purchase_analytics.js --- .../purchase_analytics/purchase_analytics.js | 36 +++++++++---------- 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/buying/page/purchase_analytics/purchase_analytics.js b/buying/page/purchase_analytics/purchase_analytics.js index c163052a6a3..6a8fc1ae0f5 100644 --- a/buying/page/purchase_analytics/purchase_analytics.js +++ b/buying/page/purchase_analytics/purchase_analytics.js @@ -4,7 +4,7 @@ wn.pages['purchase-analytics'].onload = function(wrapper) { wn.ui.make_app_page({ parent: wrapper, - title: 'Purchase Analytics', + title: wn._('Purchase Analytics'), single_column: true }); @@ -18,7 +18,7 @@ wn.pages['purchase-analytics'].onload = function(wrapper) { erpnext.PurchaseAnalytics = wn.views.TreeGridReport.extend({ init: function(wrapper) { this._super({ - title: "Purchase Analytics", + title: wn._("Purchase Analytics"), page: wrapper, parent: $(wrapper).find('.layout-main'), appframe: wrapper.appframe, @@ -31,7 +31,7 @@ erpnext.PurchaseAnalytics = wn.views.TreeGridReport.extend({ this.tree_grids = { "Supplier Type": { - label: "Supplier Type / Supplier", + label: wn._("Supplier Type / Supplier"), show: true, item_key: "supplier", parent_field: "parent_supplier_type", @@ -44,7 +44,7 @@ erpnext.PurchaseAnalytics = wn.views.TreeGridReport.extend({ } }, "Supplier": { - label: "Supplier", + label: wn._("Supplier"), show: false, item_key: "supplier", formatter: function(item) { @@ -74,7 +74,7 @@ erpnext.PurchaseAnalytics = wn.views.TreeGridReport.extend({ this.tree_grid = this.tree_grids[this.tree_type]; var std_columns = [ - {id: "check", name: "Plot", field: "check", width: 30, + {id: "check", name: wn._("Plot"), field: "check", width: 30, formatter: this.check_formatter}, {id: "name", name: this.tree_grid.label, field: "name", width: 300, formatter: this.tree_formatter}, @@ -86,23 +86,23 @@ erpnext.PurchaseAnalytics = wn.views.TreeGridReport.extend({ this.columns = std_columns.concat(this.columns); }, filters: [ - {fieldtype:"Select", label: "Tree Type", options:["Supplier Type", "Supplier", + {fieldtype:"Select", label: wn._("Tree Type"), options:["Supplier Type", "Supplier", "Item Group", "Item"], filter: function(val, item, opts, me) { return me.apply_zero_filter(val, item, opts, me); }}, - {fieldtype:"Select", label: "Based On", options:["Purchase Invoice", + {fieldtype:"Select", label: wn._("Based On"), options:["Purchase Invoice", "Purchase Order", "Purchase Receipt"]}, - {fieldtype:"Select", label: "Value or Qty", options:["Value", "Quantity"]}, - {fieldtype:"Select", label: "Company", link:"Company", + {fieldtype:"Select", label: wn._("Value or Qty"), options:["Value", "Quantity"]}, + {fieldtype:"Select", label: wn._("Company"), link:"Company", default_value: "Select Company..."}, - {fieldtype:"Date", label: "From Date"}, - {fieldtype:"Label", label: "To"}, - {fieldtype:"Date", label: "To Date"}, - {fieldtype:"Select", label: "Range", + {fieldtype:"Date", label: wn._("From Date")}, + {fieldtype:"Label", label: wn._("To")}, + {fieldtype:"Date", label: wn._("To Date")}, + {fieldtype:"Select", label: wn._("Range"), options:["Daily", "Weekly", "Monthly", "Quarterly", "Yearly"]}, - {fieldtype:"Button", label: "Refresh", icon:"icon-refresh icon-white", cssClass:"btn-info"}, - {fieldtype:"Button", label: "Reset Filters"} + {fieldtype:"Button", label: wn._("Refresh"), icon:"icon-refresh icon-white", cssClass:"btn-info"}, + {fieldtype:"Button", label: wn._("Reset Filters")} ], setup_filters: function() { var me = this; @@ -130,18 +130,18 @@ erpnext.PurchaseAnalytics = wn.views.TreeGridReport.extend({ }) wn.report_dump.data["Supplier Type"] = [{ - name: "All Supplier Types", + name: wn._("All Supplier Types"), id: "All Supplier Types", }].concat(wn.report_dump.data["Supplier Type"]); wn.report_dump.data["Supplier"].push({ - name: "Not Set", + name: wn._("Not Set"), parent_supplier_type: "All Supplier Types", id: "Not Set", }); wn.report_dump.data["Item"].push({ - name: "Not Set", + name: wn._("Not Set"), parent_item_group: "All Item Groups", id: "Not Set", }); From eb65e210fdda15eb6f35dc79bacfc53c4b8832c2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A1rbara=20Perretti?= Date: Tue, 15 Oct 2013 16:31:58 -0300 Subject: [PATCH 170/200] Fix translate hr/doctype/upload_attendance/upload_attendance.js --- hr/doctype/upload_attendance/upload_attendance.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/hr/doctype/upload_attendance/upload_attendance.js b/hr/doctype/upload_attendance/upload_attendance.js index bf584a00fc9..06a78c6735c 100644 --- a/hr/doctype/upload_attendance/upload_attendance.js +++ b/hr/doctype/upload_attendance/upload_attendance.js @@ -56,10 +56,10 @@ erpnext.hr.AttendanceControlPanel = wn.ui.form.Controller.extend({ return v; }); - r.messages = ["

    "+wn._("Import Failed!"+"

    "] + r.messages = ["

    "+wn._("Import Failed!")+"

    "] .concat(r.messages) } else { - r.messages = ["

    "+wn._("Import Successful!"+"

    "]. + r.messages = ["

    "+wn._("Import Successful!")+"

    "]. concat(r.message.messages) } From 17a37bd329def05900e0e1cb2ea24f12cd63f90c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A1rbara=20Perretti?= Date: Tue, 15 Oct 2013 16:50:53 -0300 Subject: [PATCH 171/200] Fix translate hr/doctype/job_applicant/job_applicant.js --- hr/doctype/job_applicant/job_applicant.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/hr/doctype/job_applicant/job_applicant.js b/hr/doctype/job_applicant/job_applicant.js index f82da11f07f..ccfbbc25b97 100644 --- a/hr/doctype/job_applicant/job_applicant.js +++ b/hr/doctype/job_applicant/job_applicant.js @@ -7,8 +7,8 @@ cur_frm.cscript = { onload: function(doc, dt, dn) { if(in_list(user_roles,'System Manager')) { cur_frm.footer.help_area.innerHTML = '
    \ -

    Jobs Email Settings
    \ - Automatically extract Job Applicants from a mail box e.g. "jobs@example.com"

    '; +

    '+wn._("Jobs Email Settings")+'
    \ + '+wn._('Automatically extract Job Applicants from a mail box ')+'e.g. "jobs@example.com"

    '; } }, refresh: function(doc) { From 79341409693a1ac5e73cfa78b3f2b9c1912e05e2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A1rbara=20Perretti?= Date: Tue, 15 Oct 2013 17:14:28 -0300 Subject: [PATCH 172/200] Fix translate projects/report/daily_time_log_summary/daily_time_log_summary.js --- .../report/daily_time_log_summary/daily_time_log_summary.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/projects/report/daily_time_log_summary/daily_time_log_summary.js b/projects/report/daily_time_log_summary/daily_time_log_summary.js index 6bb1117ba64..70e3cca450b 100644 --- a/projects/report/daily_time_log_summary/daily_time_log_summary.js +++ b/projects/report/daily_time_log_summary/daily_time_log_summary.js @@ -5,13 +5,13 @@ wn.query_reports["Daily Time Log Summary"] = { "filters": [ { "fieldname":"from_date", - "label": "From Date", + "label": wn._("From Date"), "fieldtype": "Date", "default": wn.datetime.get_today() }, { "fieldname":"to_date", - "label": "To Date", + "label": wn._("To Date"), "fieldtype": "Date", "default": wn.datetime.get_today() }, From a1a8907e78e952fcc363252d6b60f7186cfc7a7d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A1rbara=20Perretti?= Date: Tue, 15 Oct 2013 17:27:26 -0300 Subject: [PATCH 173/200] Fix translate startup.js --- public/js/startup.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/public/js/startup.js b/public/js/startup.js index 3853ff11cda..7d5792afb5f 100644 --- a/public/js/startup.js +++ b/public/js/startup.js @@ -44,7 +44,7 @@ erpnext.startup.show_expiry_banner = function() { msg = repl(wn._('Your ERPNext subscription will expire %(expiry_string)s. %(payment_link)s'), { expiry_string: expiry_string, payment_link: payment_link }); } else if (diff < 0) { - msg = repl(wn._('This ERPNext subscription has expired. %(payment_link)s'), {payment_link: payment_link}); + msg = repl(wn._('This ERPNext subscription')+''+wn._('has expired')+'. %(payment_link)s'), {payment_link: payment_link}); } if(msg) wn.ui.toolbar.show_banner(msg); From acc7061ca70430e469c775f949870f9a9f8e6fe4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A1rbara=20Perretti?= Date: Tue, 15 Oct 2013 17:29:57 -0300 Subject: [PATCH 174/200] Fix translate public/js/controllers/stock_controller.js --- public/js/controllers/stock_controller.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/public/js/controllers/stock_controller.js b/public/js/controllers/stock_controller.js index e4b03191a10..6fe3815555d 100644 --- a/public/js/controllers/stock_controller.js +++ b/public/js/controllers/stock_controller.js @@ -7,7 +7,7 @@ erpnext.stock.StockController = wn.ui.form.Controller.extend({ show_stock_ledger: function() { var me = this; if(this.frm.doc.docstatus===1) { - this.frm.add_custom_button("Stock Ledger", function() { + this.frm.add_custom_button(wn._("Stock Ledger"), function() { wn.route_options = { voucher_no: me.frm.doc.name, from_date: me.frm.doc.posting_date, @@ -21,7 +21,7 @@ erpnext.stock.StockController = wn.ui.form.Controller.extend({ show_general_ledger: function() { var me = this; if(this.frm.doc.docstatus===1 && cint(wn.defaults.get_default("auto_accounting_for_stock"))) { - cur_frm.add_custom_button('Accounting Ledger', function() { + cur_frm.add_custom_button(wn._('Accounting Ledger'), function() { wn.route_options = { "voucher_no": me.frm.doc.name, "from_date": me.frm.doc.posting_date, From 7329d7f118793621ce3b789beeee1ac67b697d2f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A1rbara=20Perretti?= Date: Tue, 15 Oct 2013 17:54:25 -0300 Subject: [PATCH 175/200] Fix translate selling/doctype/sales_bom/sales_bom.js --- selling/doctype/sales_bom/sales_bom.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/selling/doctype/sales_bom/sales_bom.js b/selling/doctype/sales_bom/sales_bom.js index 921d9d6683f..871420abbea 100644 --- a/selling/doctype/sales_bom/sales_bom.js +++ b/selling/doctype/sales_bom/sales_bom.js @@ -15,8 +15,8 @@ cur_frm.fields_dict.new_item_code.get_query = function() { query: "selling.doctype.sales_bom.sales_bom.get_new_item_code" } } -cur_frm.fields_dict.new_item_code.query_description = wn._('Select Item where "Is Stock Item" is "No"')+ wn._('\ - and "Is Sales Item" is "Yes" and there is no other Sales BOM'); +cur_frm.fields_dict.new_item_code.query_description = wn._('Select Item where "Is Stock Item" is "No"')+ +wn._('and "Is Sales Item" is "Yes" and there is no other Sales BOM'); cur_frm.cscript.item_code = function(doc, dt, dn) { var d = locals[dt][dn]; From 9d6312fac4c933e9d1571642c5ef169ea38a9e9b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A1rbara=20Perretti?= Date: Tue, 15 Oct 2013 17:57:20 -0300 Subject: [PATCH 176/200] Fix translate customers_not_buying_since_long_time.js --- .../customers_not_buying_since_long_time.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/selling/report/customers_not_buying_since_long_time/customers_not_buying_since_long_time.js b/selling/report/customers_not_buying_since_long_time/customers_not_buying_since_long_time.js index d527b344b88..78c38286c25 100644 --- a/selling/report/customers_not_buying_since_long_time/customers_not_buying_since_long_time.js +++ b/selling/report/customers_not_buying_since_long_time/customers_not_buying_since_long_time.js @@ -5,7 +5,7 @@ wn.query_reports["Customers Not Buying Since Long Time"] = { "filters": [ { "fieldname":"days_since_last_order", - "label": "Days Since Last Order", + "label": wn._("Days Since Last Order"), "fieldtype": "Int", "default": 60 } From 119326826a9482cd654c4eb6359845ba88751a2f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A1rbara=20Perretti?= Date: Tue, 15 Oct 2013 18:14:50 -0300 Subject: [PATCH 177/200] Fix translate setup/doctype/territory/territory.js --- setup/doctype/territory/territory.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup/doctype/territory/territory.js b/setup/doctype/territory/territory.js index 75618161854..de708b6d052 100644 --- a/setup/doctype/territory/territory.js +++ b/setup/doctype/territory/territory.js @@ -9,7 +9,7 @@ cur_frm.cscript.set_root_readonly = function(doc) { // read-only for root territory if(!doc.parent_territory) { cur_frm.perm = [[1,0,0], [1,0,0]]; - cur_frm.set_intro("This is a root territory and cannot be edited."); + cur_frm.set_intro(wn._("This is a root territory and cannot be edited.")); } else { cur_frm.set_intro(null); } From 058e246be68e1a15e8efb59da260a68518089877 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A1rbara=20Perretti?= Date: Tue, 15 Oct 2013 18:15:29 -0300 Subject: [PATCH 178/200] Fix translate supplier_type.js --- setup/doctype/supplier_type/supplier_type.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup/doctype/supplier_type/supplier_type.js b/setup/doctype/supplier_type/supplier_type.js index b65f67c21ca..5ebf6d51e2d 100644 --- a/setup/doctype/supplier_type/supplier_type.js +++ b/setup/doctype/supplier_type/supplier_type.js @@ -2,5 +2,5 @@ // License: GNU General Public License v3. See license.txt cur_frm.cscript.refresh = function(doc) { - cur_frm.set_intro(doc.__islocal ? "" : "There is nothing to edit.") + cur_frm.set_intro(doc.__islocal ? "" : wn._("There is nothing to edit.")) } \ No newline at end of file From b7a6b850cfe324d22cbf49ba1b21c7b487e7eff4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A1rbara=20Perretti?= Date: Tue, 15 Oct 2013 18:20:32 -0300 Subject: [PATCH 179/200] Fix translate setup.js --- setup/page/setup/setup.js | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/setup/page/setup/setup.js b/setup/page/setup/setup.js index f39618685d2..0127a2a3f09 100644 --- a/setup/page/setup/setup.js +++ b/setup/page/setup/setup.js @@ -5,12 +5,12 @@ wn.pages['Setup'].onload = function(wrapper) { if(msg_dialog && msg_dialog.display) msg_dialog.hide(); wn.ui.make_app_page({ parent: wrapper, - title: 'Setup', + title: wn._('Setup'), single_column: true }); wrapper.appframe.add_module_icon("Setup"); - wrapper.appframe.add_button("Refresh", function() { + wrapper.appframe.add_button(wn._("Refresh"), function() { wn.pages.Setup.make(wrapper); }, "icon-refresh"); @@ -110,7 +110,7 @@ wn.pages.Setup.make = function(wrapper) { }) } else if(item.single) { - $(' Edit') + $(''+wn._('Edit')+'') .appendTo($links) $links.find(".view-link") @@ -119,11 +119,11 @@ wn.pages.Setup.make = function(wrapper) { wn.set_route("Form", $(this).attr("data-doctype")); }) } else if(item.type !== "Link"){ - $(' New \ + $(''+wn._('New')+' \ | \ - View \ + '+wn._('View')+' \ | \ - Import') + '+wn._('Import')+'') .appendTo($links) $links.find(".view-link") @@ -180,11 +180,11 @@ wn.pages.Setup.make = function(wrapper) { if(r.message) { body.empty(); if(wn.boot.expires_on) { - $(body).prepend("
    Account expires on " + $(body).prepend("
    "+wn.("Account expires on") + wn.datetime.global_date_format(wn.boot.expires_on) + "
    "); } - $completed = $('

    Setup Completed

    \ + $completed = $('

    '+wn._("Setup Completed")+'

    \
    ') .appendTo(body); From f007dd4e5f40e993141cca6626a5232303d8c172 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A1rbara=20Perretti?= Date: Tue, 15 Oct 2013 18:32:38 -0300 Subject: [PATCH 180/200] Fix translate stock/page/stock_ageing/stock_ageing.js --- stock/page/stock_ageing/stock_ageing.js | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/stock/page/stock_ageing/stock_ageing.js b/stock/page/stock_ageing/stock_ageing.js index 98f7ace40f3..914999b2052 100644 --- a/stock/page/stock_ageing/stock_ageing.js +++ b/stock/page/stock_ageing/stock_ageing.js @@ -30,21 +30,21 @@ erpnext.StockAgeing = erpnext.StockGridReport.extend({ }, setup_columns: function() { this.columns = [ - {id: "name", name: "Item", field: "name", width: 300, + {id: "name", name: wn._("Item"), field: "name", width: 300, link_formatter: { open_btn: true, doctype: '"Item"' }}, - {id: "item_name", name: "Item Name", field: "item_name", + {id: "item_name", name: wn._("Item Name"), field: "item_name", width: 100, formatter: this.text_formatter}, - {id: "description", name: "Description", field: "description", + {id: "description", name: wn._("Description"), field: "description", width: 200, formatter: this.text_formatter}, - {id: "brand", name: "Brand", field: "brand", width: 100}, - {id: "average_age", name: "Average Age", field: "average_age", + {id: "brand", name: wn._("Brand"), field: "brand", width: 100}, + {id: "average_age", name: wn._("Average Age"), field: "average_age", formatter: this.currency_formatter}, - {id: "earliest", name: "Earliest", field: "earliest", + {id: "earliest", name: wn._("Earliest"), field: "earliest", formatter: this.currency_formatter}, - {id: "latest", name: "Latest", field: "latest", + {id: "latest", name: wn._("Latest"), field: "latest", formatter: this.currency_formatter}, {id: "stock_uom", name: "UOM", field: "stock_uom", width: 100}, ]; From 3da50f09609d12385134663db77cfc237cabc2a4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A1rbara=20Perretti?= Date: Tue, 15 Oct 2013 18:34:18 -0300 Subject: [PATCH 181/200] Fix translate stock/page/stock_home/stock_home.js --- stock/page/stock_home/stock_home.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stock/page/stock_home/stock_home.js b/stock/page/stock_home/stock_home.js index 63db6086abd..e99c1fccd02 100644 --- a/stock/page/stock_home/stock_home.js +++ b/stock/page/stock_home/stock_home.js @@ -106,7 +106,7 @@ wn.module_page["Stock"] = [ "label": wn._("Stock Settings"), "route": "Form/Stock Settings", "doctype":"Stock Settings", - "description": "Settings for Stock Module" + "description": wn._("Settings for Stock Module") }, { "route":"Sales Browser/Item Group", From 62944524350a6b4379deeb905a2d069e20cbab2c Mon Sep 17 00:00:00 2001 From: Anand Doshi Date: Thu, 17 Oct 2013 20:00:52 +0530 Subject: [PATCH 182/200] [minor] removed references to server.py --- stock/doctype/item/templates/includes/product_list.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stock/doctype/item/templates/includes/product_list.js b/stock/doctype/item/templates/includes/product_list.js index 2856bde3d71..efcbe0b2a57 100644 --- a/stock/doctype/item/templates/includes/product_list.js +++ b/stock/doctype/item/templates/includes/product_list.js @@ -12,7 +12,7 @@ window.get_product_list = function() { $.ajax({ method: "GET", - url: "server.py", + url: "/", dataType: "json", data: { cmd: "selling.utils.product.get_product_list", From 46eaa55f06006ac592db57829e4c12956b11a986 Mon Sep 17 00:00:00 2001 From: Rushabh Mehta Date: Fri, 18 Oct 2013 12:16:56 +0530 Subject: [PATCH 183/200] [editable] [minor] made item, item_group pages editable --- .../item_group/templates/generators/item_group.html | 10 +++++++++- stock/doctype/item/templates/generators/item.html | 8 ++++++++ 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/setup/doctype/item_group/templates/generators/item_group.html b/setup/doctype/item_group/templates/generators/item_group.html index 48db596f843..459c9896c4c 100644 --- a/setup/doctype/item_group/templates/generators/item_group.html +++ b/setup/doctype/item_group/templates/generators/item_group.html @@ -8,7 +8,7 @@ {% include "lib/website/doctype/website_slideshow/templates/includes/slideshow.html" %} {% endif %} {% if description %} -
    {{ description or ""}}
    +
    {{ description or ""}}
    {% else %}

    {{ name }}

    {% endif %} @@ -38,5 +38,13 @@
    No items listed.
    {% endif %}

    + {% endblock %} \ No newline at end of file diff --git a/stock/doctype/item/templates/generators/item.html b/stock/doctype/item/templates/generators/item.html index 7056068e9b5..eab1b73a548 100644 --- a/stock/doctype/item/templates/generators/item.html +++ b/stock/doctype/item/templates/generators/item.html @@ -3,6 +3,14 @@ {% block javascript %} {% endblock %} From 096d36308782236be894645bc322f30b300392fd Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Thu, 17 Oct 2013 17:01:14 +0530 Subject: [PATCH 184/200] [fix] fixed merge conflict --- .../purchase_invoice/purchase_invoice.py | 15 +++- .../doctype/sales_invoice/sales_invoice.js | 56 ++++++-------- .../doctype/sales_invoice/sales_invoice.py | 1 - controllers/accounts_controller.py | 6 +- controllers/buying_controller.py | 2 +- controllers/selling_controller.py | 6 +- docs/user/setup/docs.user.setup.price_list.md | 2 +- docs/user/stock/docs.user.stock.item.md | 4 +- install_erpnext.py | 4 +- public/js/controllers/stock_controller.js | 12 +++ public/js/transaction.js | 25 ++++--- selling/doctype/quotation/quotation.py | 3 +- selling/doctype/sales_common/sales_common.py | 14 ---- selling/doctype/sales_order/sales_order.py | 2 +- stock/doctype/delivery_note/delivery_note.py | 2 +- stock/doctype/stock_entry/stock_entry.js | 75 ++++++++++++------- stock/doctype/stock_entry/stock_entry.py | 6 +- .../stock_entry_detail/stock_entry_detail.txt | 3 +- 18 files changed, 130 insertions(+), 108 deletions(-) diff --git a/accounts/doctype/purchase_invoice/purchase_invoice.py b/accounts/doctype/purchase_invoice/purchase_invoice.py index c65b9acb2b9..8bd7e9df032 100644 --- a/accounts/doctype/purchase_invoice/purchase_invoice.py +++ b/accounts/doctype/purchase_invoice/purchase_invoice.py @@ -353,6 +353,7 @@ class DocType(BuyingController): # item gl entries stock_item_and_auto_accounting_for_stock = False stock_items = self.get_stock_items() + rounding_diff = 0.0 for item in self.doclist.get({"parentfield": "entries"}): if auto_accounting_for_stock and item.item_code in stock_items: if flt(item.valuation_rate): @@ -361,9 +362,13 @@ class DocType(BuyingController): # expense will be booked in sales invoice stock_item_and_auto_accounting_for_stock = True - valuation_amt = (flt(item.amount, self.precision("amount", item)) + + valuation_amt = flt(flt(item.valuation_rate) * flt(item.qty) * \ + flt(item.conversion_factor), self.precision("valuation_rate", item)) + + rounding_diff += (flt(item.amount, self.precision("amount", item)) + flt(item.item_tax_amount, self.precision("item_tax_amount", item)) + - flt(item.rm_supp_cost, self.precision("rm_supp_cost", item))) + flt(item.rm_supp_cost, self.precision("rm_supp_cost", item)) - + valuation_amt) gl_entries.append( self.get_gl_dict({ @@ -392,6 +397,12 @@ class DocType(BuyingController): expenses_included_in_valuation = \ self.get_company_default("expenses_included_in_valuation") + if rounding_diff: + import operator + cost_center_with_max_value = max(valuation_tax.iteritems(), + key=operator.itemgetter(1))[0] + valuation_tax[cost_center_with_max_value] -= flt(rounding_diff) + for cost_center, amount in valuation_tax.items(): gl_entries.append( self.get_gl_dict({ diff --git a/accounts/doctype/sales_invoice/sales_invoice.js b/accounts/doctype/sales_invoice/sales_invoice.js index aa4301cd47c..6f35f92fb22 100644 --- a/accounts/doctype/sales_invoice/sales_invoice.js +++ b/accounts/doctype/sales_invoice/sales_invoice.js @@ -18,21 +18,21 @@ wn.provide("erpnext.accounts"); erpnext.accounts.SalesInvoiceController = erpnext.selling.SellingController.extend({ onload: function() { this._super(); - - if(!this.frm.doc.__islocal) { + + if(!this.frm.doc.__islocal && !this.frm.doc.customer && this.frm.doc.debit_to) { // show debit_to in print format - if(!this.frm.doc.customer && this.frm.doc.debit_to) { - this.frm.set_df_property("debit_to", "print_hide", 0); - } + this.frm.set_df_property("debit_to", "print_hide", 0); } // toggle to pos view if is_pos is 1 in user_defaults - if ((cint(wn.defaults.get_user_defaults("is_pos"))===1 || cur_frm.doc.is_pos) && - cint(wn.defaults.get_user_defaults("fs_pos_view"))===1) { - if(this.frm.doc.__islocal && !this.frm.doc.amended_from) { - this.frm.set_value("is_pos", 1); - this.is_pos(function() {cur_frm.cscript.toggle_pos(true);}); - } + if ((cint(wn.defaults.get_user_defaults("is_pos"))===1 || cur_frm.doc.is_pos)) { + if(this.frm.doc.__islocal && !this.frm.doc.amended_from && !this.frm.doc.customer) { + this.frm.set_value("is_pos", 1); + this.is_pos(function() { + if (cint(wn.defaults.get_user_defaults("fs_pos_view"))===1) + cur_frm.cscript.toggle_pos(true); + }); + } } // if document is POS then change default print format to "POS Invoice" @@ -44,7 +44,7 @@ erpnext.accounts.SalesInvoiceController = erpnext.selling.SellingController.exte refresh: function(doc, dt, dn) { this._super(); - + cur_frm.cscript.is_opening(doc, dt, dn); cur_frm.dashboard.reset(); @@ -141,6 +141,10 @@ erpnext.accounts.SalesInvoiceController = erpnext.selling.SellingController.exte callback: function(r) { if(!r.exc) { me.frm.script_manager.trigger("update_stock"); + me.set_default_values(); + me.set_dynamic_labels(); + me.calculate_taxes_and_totals(); + if(callback_fn) callback_fn() } } @@ -350,7 +354,7 @@ if (sys_defaults.auto_accounting_for_stock) { // warehouse in detail table //---------------------------- -cur_frm.fields_dict['entries'].grid.get_field('warehouse').get_query= function(doc, cdt, cdn) { +cur_frm.fields_dict['entries'].grid.get_field('warehouse').get_query = function(doc, cdt, cdn) { var d = locals[cdt][cdn]; return{ filters:[ @@ -371,34 +375,16 @@ cur_frm.fields_dict["entries"].grid.get_field("cost_center").get_query = functio } } -cur_frm.cscript.income_account = function(doc, cdt, cdn){ +cur_frm.cscript.income_account = function(doc, cdt, cdn) { cur_frm.cscript.copy_account_in_all_row(doc, cdt, cdn, "income_account"); } -cur_frm.cscript.expense_account = function(doc, cdt, cdn){ +cur_frm.cscript.expense_account = function(doc, cdt, cdn) { cur_frm.cscript.copy_account_in_all_row(doc, cdt, cdn, "expense_account"); } -cur_frm.cscript.copy_account_in_all_row = function(doc, cdt, cdn, fieldname) { - var d = locals[cdt][cdn]; - if(d[fieldname]){ - var cl = getchildren('Sales Invoice Item', doc.name, cur_frm.cscript.fname, doc.doctype); - for(var i = 0; i < cl.length; i++){ - if(!cl[i][fieldname]) cl[i][fieldname] = d[fieldname]; - } - } - refresh_field(cur_frm.cscript.fname); -} - -cur_frm.cscript.cost_center = function(doc, cdt, cdn){ - var d = locals[cdt][cdn]; - if(d.cost_center){ - var cl = getchildren('Sales Invoice 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.cscript.cost_center = function(doc, cdt, cdn) { + cur_frm.cscript.copy_account_in_all_row(doc, cdt, cdn, "cost_center"); } cur_frm.cscript.on_submit = function(doc, cdt, cdn) { diff --git a/accounts/doctype/sales_invoice/sales_invoice.py b/accounts/doctype/sales_invoice/sales_invoice.py index 92c168008a1..b6548c05984 100644 --- a/accounts/doctype/sales_invoice/sales_invoice.py +++ b/accounts/doctype/sales_invoice/sales_invoice.py @@ -52,7 +52,6 @@ class DocType(SellingController): sales_com_obj = get_obj('Sales Common') sales_com_obj.check_stop_sales_order(self) sales_com_obj.check_active_sales_items(self) - sales_com_obj.check_conversion_rate(self) sales_com_obj.validate_max_discount(self, 'entries') self.validate_customer_account() self.validate_debit_acc() diff --git a/controllers/accounts_controller.py b/controllers/accounts_controller.py index 5121d69f6a5..9b2e28b3a9e 100644 --- a/controllers/accounts_controller.py +++ b/controllers/accounts_controller.py @@ -52,7 +52,7 @@ class AccountsController(TransactionBase): msgprint(_("Account for this ") + fieldname + _(" has been freezed. ") + self.doc.doctype + _(" can not be made."), raise_exception=1) - def set_price_list_currency(self, buying_or_selling, for_validate=False): + def set_price_list_currency(self, buying_or_selling): if self.meta.get_field("currency"): company_currency = get_company_currency(self.doc.company) @@ -66,7 +66,7 @@ class AccountsController(TransactionBase): if self.doc.price_list_currency == company_currency: self.doc.plc_conversion_rate = 1.0 - elif not self.doc.plc_conversion_rate or not for_validate: + elif not self.doc.plc_conversion_rate: self.doc.plc_conversion_rate = self.get_exchange_rate( self.doc.price_list_currency, company_currency) @@ -76,7 +76,7 @@ class AccountsController(TransactionBase): self.doc.conversion_rate = self.doc.plc_conversion_rate elif self.doc.currency == company_currency: self.doc.conversion_rate = 1.0 - elif not self.doc.conversion_rate or not for_validate: + elif not self.doc.conversion_rate: self.doc.conversion_rate = self.get_exchange_rate(self.doc.currency, company_currency) diff --git a/controllers/buying_controller.py b/controllers/buying_controller.py index 5176b1612a7..c42eda50bc9 100644 --- a/controllers/buying_controller.py +++ b/controllers/buying_controller.py @@ -29,7 +29,7 @@ class BuyingController(StockController): super(BuyingController, self).set_missing_values(for_validate) self.set_supplier_from_item_default() - self.set_price_list_currency("Buying", for_validate) + self.set_price_list_currency("Buying") # set contact and address details for supplier, if they are not mentioned if self.doc.supplier and not (self.doc.contact_person and self.doc.supplier_address): diff --git a/controllers/selling_controller.py b/controllers/selling_controller.py index 5c7b66c82ec..d78cf932b46 100644 --- a/controllers/selling_controller.py +++ b/controllers/selling_controller.py @@ -23,7 +23,7 @@ class SellingController(StockController): # set contact and address details for customer, if they are not mentioned self.set_missing_lead_customer_details() - self.set_price_list_and_item_details(for_validate) + self.set_price_list_and_item_details() if self.doc.fields.get("__islocal"): self.set_taxes("other_charges", "charge") @@ -41,8 +41,8 @@ class SellingController(StockController): if not self.doc.fields.get(fieldname) and self.meta.get_field(fieldname): self.doc.fields[fieldname] = val - def set_price_list_and_item_details(self, for_validate=False): - self.set_price_list_currency("Selling", for_validate) + def set_price_list_and_item_details(self): + self.set_price_list_currency("Selling") self.set_missing_item_details(get_item_details) def get_other_charges(self): diff --git a/docs/user/setup/docs.user.setup.price_list.md b/docs/user/setup/docs.user.setup.price_list.md index 7214fff5143..a1fbf89a1ee 100644 --- a/docs/user/setup/docs.user.setup.price_list.md +++ b/docs/user/setup/docs.user.setup.price_list.md @@ -20,7 +20,7 @@ An Item can have multiple prices based on customer, currency, region, shipping c > Setup > Item Price -- Enter Price List and Item Code, Valid for Buying or Selling, Item Name & Item Description will be automatically fetched. +- Enter Price List and Item Code, Valid for Buying or Selling, Item Name and Item Description will be automatically fetched. - Enter Rate and save the document. ![Item-Price](img/item-price.png) diff --git a/docs/user/stock/docs.user.stock.item.md b/docs/user/stock/docs.user.stock.item.md index f7746c48423..fdf304559b0 100644 --- a/docs/user/stock/docs.user.stock.item.md +++ b/docs/user/stock/docs.user.stock.item.md @@ -38,11 +38,11 @@ In ERPNext, you can select different type of Warehouses to stock your different ### Serialized and Batched Inventory -These numbers help to track individual units or batches of Items which you sell. It also tracks warranty and returns. In case any individual Item is recalled by the supplier the number system helps to track individual Item. The numbering system also manages expiry dates. Please note that if you sell your items in thousands, and if the items are very small like pens or erasers, you need not serialize them. In ERPNext, you will have to mention the serial number in some accounting entries. To create serial numbers you will have to manually create all the numbers in your entries. If your product is not a big consumer durable Item, if it has no warranty and has no chances of being recalled, avoid giving serial numbers. +These numbers help to track individual units or batches of Items which you sell. It also tracks warranty and returns. In case any individual Item is recalled by the supplier the number system helps to track individual Item. The numbering system also manages expiry dates. Please note that if you sell your items in thousands, and if the items are very small like pens or erasers, you need not serialize them. In ERPNext, you will have to mention the serial number in some accounting entries. To create serial numbers you will have to manually create all the numbers in your entries. If your product is not a big consumer durable Item, if it has no warranty and has no chances of being recalled, avoid giving serial numbers. > Important: Once you mark an item as serialized or batched or neither, you cannot change it after you have made any stock entry. -- [Disucssion on Serialized Inventory](docs.user.stock.serialized.html) +- [Discussion on Serialized Inventory](docs.user.stock.serialized.html) ### Re Ordering diff --git a/install_erpnext.py b/install_erpnext.py index 79f79d7cc0a..7f3b8c3b655 100644 --- a/install_erpnext.py +++ b/install_erpnext.py @@ -332,9 +332,11 @@ def exec_in_shell(cmd): stdout.seek(0) out = stdout.read() + if out: out = out.decode('utf-8') stderr.seek(0) err = stderr.read() + if err: err = err.decode('utf-8') if err and any((kw in err.lower() for kw in ["traceback", "error", "exception"])): print out @@ -345,4 +347,4 @@ def exec_in_shell(cmd): return out if __name__ == "__main__": - install() \ No newline at end of file + install() diff --git a/public/js/controllers/stock_controller.js b/public/js/controllers/stock_controller.js index e4b03191a10..de18fe0b579 100644 --- a/public/js/controllers/stock_controller.js +++ b/public/js/controllers/stock_controller.js @@ -18,6 +18,7 @@ erpnext.stock.StockController = wn.ui.form.Controller.extend({ } }, + show_general_ledger: function() { var me = this; if(this.frm.doc.docstatus===1 && cint(wn.defaults.get_default("auto_accounting_for_stock"))) { @@ -30,5 +31,16 @@ erpnext.stock.StockController = wn.ui.form.Controller.extend({ wn.set_route("general-ledger"); }); } + }, + + copy_account_in_all_row: function(doc, dt, dn, fieldname) { + var d = locals[dt][dn]; + if(d[fieldname]){ + var cl = getchildren(this.frm.cscript.tname, doc.name, this.frm.cscript.fname, doc.doctype); + for(var i = 0; i < cl.length; i++) { + if(!cl[i][fieldname]) cl[i][fieldname] = d[fieldname]; + } + } + refresh_field(this.frm.cscript.fname); } }); \ No newline at end of file diff --git a/public/js/transaction.js b/public/js/transaction.js index 79ea53623fe..2886e1ca8f7 100644 --- a/public/js/transaction.js +++ b/public/js/transaction.js @@ -24,11 +24,9 @@ erpnext.TransactionController = erpnext.stock.StockController.extend({ }, function(fieldname, value) { if(me.frm.fields_dict[fieldname] && !me.frm.doc[fieldname]) me.frm.set_value(fieldname, value); - }); - - me.frm.script_manager.trigger("company"); + }); } - + if(this.other_fname) { this[this.other_fname + "_remove"] = this.calculate_taxes_and_totals; } @@ -39,9 +37,9 @@ erpnext.TransactionController = erpnext.stock.StockController.extend({ }, onload_post_render: function() { - if(this.frm.doc.__islocal && this.frm.doc.company && - !this.frm.doc.customer && !this.frm.doc.is_pos) { - var me = this; + var me = this; + if(this.frm.doc.__islocal && this.frm.doc.company && !this.frm.doc.is_pos) { + if(!this.frm.doc.customer || !this.frm.doc.supplier) { return this.frm.call({ doc: this.frm.doc, method: "onload_post_render", @@ -50,8 +48,12 @@ erpnext.TransactionController = erpnext.stock.StockController.extend({ // remove this call when using client side mapper me.set_default_values(); me.set_dynamic_labels(); + me.calculate_taxes_and_totals(); } }); + } else { + this.calculate_taxes_and_totals(); + } } }, @@ -169,12 +171,12 @@ erpnext.TransactionController = erpnext.stock.StockController.extend({ conversion_rate: function() { if(this.frm.doc.currency === this.get_company_currency()) { this.frm.set_value("conversion_rate", 1.0); - } else if(this.frm.doc.currency === this.frm.doc.price_list_currency && + } + if(this.frm.doc.currency === this.frm.doc.price_list_currency && this.frm.doc.plc_conversion_rate !== this.frm.doc.conversion_rate) { this.frm.set_value("plc_conversion_rate", this.frm.doc.conversion_rate); } - - this.calculate_taxes_and_totals(); + if(flt(this.frm.doc.conversion_rate)>0.0) this.calculate_taxes_and_totals(); }, get_price_list_currency: function(buying_or_selling) { @@ -224,7 +226,8 @@ erpnext.TransactionController = erpnext.stock.StockController.extend({ plc_conversion_rate: function() { if(this.frm.doc.price_list_currency === this.get_company_currency()) { this.frm.set_value("plc_conversion_rate", 1.0); - } else if(this.frm.doc.price_list_currency === this.frm.doc.currency) { + } + if(this.frm.doc.price_list_currency === this.frm.doc.currency) { this.frm.set_value("conversion_rate", this.frm.doc.plc_conversion_rate); this.calculate_taxes_and_totals(); } diff --git a/selling/doctype/quotation/quotation.py b/selling/doctype/quotation/quotation.py index 78afb97404e..bd158d580af 100644 --- a/selling/doctype/quotation/quotation.py +++ b/selling/doctype/quotation/quotation.py @@ -102,8 +102,7 @@ class DocType(SellingController): sales_com_obj = get_obj('Sales Common') sales_com_obj.check_active_sales_items(self) sales_com_obj.validate_max_discount(self,'quotation_details') - sales_com_obj.check_conversion_rate(self) - + #update enquiry #------------------ def update_opportunity(self): diff --git a/selling/doctype/sales_common/sales_common.py b/selling/doctype/sales_common/sales_common.py index 01718dd3f0b..e1172eb5660 100644 --- a/selling/doctype/sales_common/sales_common.py +++ b/selling/doctype/sales_common/sales_common.py @@ -9,7 +9,6 @@ from webnotes.model.doc import addchild from webnotes.model.bean import getlist from webnotes.model.code import get_obj from webnotes import msgprint, _ -from setup.utils import get_company_currency get_value = webnotes.conn.get_value @@ -73,19 +72,6 @@ class DocType(TransactionBase): if discount and discount[0]['max_discount'] and (flt(d.adj_rate)>flt(discount[0]['max_discount'])): msgprint("You cannot give more than " + cstr(discount[0]['max_discount']) + " % discount on Item Code : "+cstr(d.item_code)) raise Exception - - # Check Conversion Rate (i.e. it will not allow conversion rate to be 1 for Currency other than default currency set in Global Defaults) - # =========================================================================== - def check_conversion_rate(self, obj): - default_currency = get_company_currency(obj.doc.company) - if not default_currency: - msgprint('Message: Please enter default currency in Company Master') - raise Exception - if (obj.doc.currency == default_currency and flt(obj.doc.conversion_rate) != 1.00) or not obj.doc.conversion_rate or (obj.doc.currency != default_currency and flt(obj.doc.conversion_rate) == 1.00): - msgprint("Please Enter Appropriate Conversion Rate for Customer's Currency to Base Currency (%s --> %s)" % (obj.doc.currency, default_currency), raise_exception = 1) - - if (obj.doc.price_list_currency == default_currency and flt(obj.doc.plc_conversion_rate) != 1.00) or not obj.doc.plc_conversion_rate or (obj.doc.price_list_currency != default_currency and flt(obj.doc.plc_conversion_rate) == 1.00): - msgprint("Please Enter Appropriate Conversion Rate for Price List Currency to Base Currency (%s --> %s)" % (obj.doc.price_list_currency, default_currency), raise_exception = 1) def get_item_list(self, obj, is_stopped=0): """get item list""" diff --git a/selling/doctype/sales_order/sales_order.py b/selling/doctype/sales_order/sales_order.py index 1c22c08a3b6..6dfa3e2ec5b 100644 --- a/selling/doctype/sales_order/sales_order.py +++ b/selling/doctype/sales_order/sales_order.py @@ -126,7 +126,7 @@ class DocType(SellingController): self.validate_warehouse() sales_com_obj = get_obj(dt = 'Sales Common') sales_com_obj.check_active_sales_items(self) - sales_com_obj.check_conversion_rate(self) + sales_com_obj.validate_max_discount(self,'sales_order_details') self.doclist = sales_com_obj.make_packing_list(self,'sales_order_details') diff --git a/stock/doctype/delivery_note/delivery_note.py b/stock/doctype/delivery_note/delivery_note.py index deaf024a2ea..897c7d4d32a 100644 --- a/stock/doctype/delivery_note/delivery_note.py +++ b/stock/doctype/delivery_note/delivery_note.py @@ -91,7 +91,7 @@ class DocType(SellingController): self.validate_uom_is_integer("stock_uom", "qty") sales_com_obj.validate_max_discount(self, 'delivery_note_details') - sales_com_obj.check_conversion_rate(self) + # Set actual qty for each item in selected warehouse self.update_current_stock() diff --git a/stock/doctype/stock_entry/stock_entry.js b/stock/doctype/stock_entry/stock_entry.js index 4695fdb22c2..7301bd5b1ad 100644 --- a/stock/doctype/stock_entry/stock_entry.js +++ b/stock/doctype/stock_entry/stock_entry.js @@ -1,6 +1,9 @@ // Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. // License: GNU General Public License v3. See license.txt +cur_frm.cscript.tname = "Stock Entry Detail"; +cur_frm.cscript.fname = "mtn_details"; + wn.require("public/app/js/controllers/stock_controller.js"); wn.provide("erpnext.stock"); @@ -112,12 +115,6 @@ erpnext.stock.StockEntry = erpnext.stock.StockController.extend({ } }, - entries_add: function(doc, cdt, cdn) { - var row = wn.model.get_doc(cdt, cdn); - this.frm.script_manager.copy_from_first_row("mtn_details", row, - ["expense_account", "cost_center"]); - }, - clean_up: function() { // Clear Production Order record from locals, because it is updated via Stock Entry if(this.frm.doc.production_order && @@ -224,6 +221,8 @@ erpnext.stock.StockEntry = erpnext.stock.StockController.extend({ mtn_details_add: function(doc, cdt, cdn) { var row = wn.model.get_doc(cdt, cdn); + this.frm.script_manager.copy_from_first_row("mtn_details", row, + ["expense_account", "cost_center"]); if(!row.s_warehouse) row.s_warehouse = this.frm.doc.from_warehouse; if(!row.t_warehouse) row.t_warehouse = this.frm.doc.to_warehouse; @@ -260,24 +259,29 @@ cur_frm.cscript.toggle_related_fields = function(doc) { } } -cur_frm.cscript.delivery_note_no = function(doc,cdt,cdn){ - if(doc.delivery_note_no) return get_server_fields('get_cust_values','','',doc,cdt,cdn,1); +cur_frm.cscript.delivery_note_no = function(doc, cdt, cdn) { + if(doc.delivery_note_no) + return get_server_fields('get_cust_values', '', '', doc, cdt, cdn, 1); } -cur_frm.cscript.sales_invoice_no = function(doc,cdt,cdn){ - if(doc.sales_invoice_no) return get_server_fields('get_cust_values','','',doc,cdt,cdn,1); +cur_frm.cscript.sales_invoice_no = function(doc, cdt, cdn) { + if(doc.sales_invoice_no) + return get_server_fields('get_cust_values', '', '', doc, cdt, cdn, 1); } -cur_frm.cscript.customer = function(doc,cdt,cdn){ - if(doc.customer) return get_server_fields('get_cust_addr','','',doc,cdt,cdn,1); +cur_frm.cscript.customer = function(doc, cdt, cdn) { + if(doc.customer) + return get_server_fields('get_cust_addr', '', '', doc, cdt, cdn, 1); } -cur_frm.cscript.purchase_receipt_no = function(doc,cdt,cdn){ - if(doc.purchase_receipt_no) return get_server_fields('get_supp_values','','',doc,cdt,cdn,1); +cur_frm.cscript.purchase_receipt_no = function(doc, cdt, cdn) { + if(doc.purchase_receipt_no) + return get_server_fields('get_supp_values', '', '', doc, cdt, cdn, 1); } -cur_frm.cscript.supplier = function(doc,cdt,cdn){ - if(doc.supplier) return get_server_fields('get_supp_addr','','',doc,cdt,cdn,1); +cur_frm.cscript.supplier = function(doc, cdt, cdn) { + if(doc.supplier) + return get_server_fields('get_supp_addr', '', '', doc, cdt, cdn, 1); } @@ -314,13 +318,17 @@ cur_frm.fields_dict['mtn_details'].grid.get_field('batch_no').get_query = functi cur_frm.cscript.item_code = function(doc, cdt, cdn) { var d = locals[cdt][cdn]; args = { - 'item_code' : d.item_code, - 'warehouse' : cstr(d.s_warehouse) || cstr(d.t_warehouse), - 'transfer_qty' : d.transfer_qty, - 'serial_no' : d.serial_no, - 'bom_no' : d.bom_no + 'item_code' : d.item_code, + 'warehouse' : cstr(d.s_warehouse) || cstr(d.t_warehouse), + 'transfer_qty' : d.transfer_qty, + 'serial_no' : d.serial_no, + 'bom_no' : d.bom_no, + 'expense_account' : d.expense_account, + 'cost_center' : d.cost_center, + 'company' : cur_frm.doc.company }; - return get_server_fields('get_item_details',JSON.stringify(args),'mtn_details',doc,cdt,cdn,1); + return get_server_fields('get_item_details', JSON.stringify(args), + 'mtn_details', doc, cdt, cdn, 1); } cur_frm.cscript.s_warehouse = function(doc, cdt, cdn) { @@ -343,7 +351,8 @@ cur_frm.cscript.uom = function(doc, cdt, cdn) { var d = locals[cdt][cdn]; if(d.uom && d.item_code){ var arg = {'item_code':d.item_code, 'uom':d.uom, 'qty':d.qty} - return get_server_fields('get_uom_details',JSON.stringify(arg),'mtn_details', doc, cdt, cdn, 1); + return get_server_fields('get_uom_details', JSON.stringify(arg), + 'mtn_details', doc, cdt, cdn, 1); } } @@ -354,15 +363,25 @@ cur_frm.cscript.validate = function(doc, cdt, cdn) { } cur_frm.cscript.validate_items = function(doc) { - cl = getchildren('Stock Entry Detail',doc.name,'mtn_details'); + cl = getchildren('Stock Entry Detail', doc.name, 'mtn_details'); if (!cl.length) { alert("Item table can not be blank"); validated = false; } } -cur_frm.fields_dict.customer.get_query = function(doc,cdt,cdn) { - return{ query:"controllers.queries.customer_query" } } +cur_frm.cscript.expense_account = function(doc, cdt, cdn) { + cur_frm.cscript.copy_account_in_all_row(doc, cdt, cdn, "expense_account"); +} -cur_frm.fields_dict.supplier.get_query = function(doc,cdt,cdn) { - return{ query:"controllers.queries.supplier_query" } } +cur_frm.cscript.cost_center = function(doc, cdt, cdn) { + cur_frm.cscript.copy_account_in_all_row(doc, cdt, cdn, "cost_center"); +} + +cur_frm.fields_dict.customer.get_query = function(doc, cdt, cdn) { + return{ query:"controllers.queries.customer_query" } +} + +cur_frm.fields_dict.supplier.get_query = function(doc, cdt, cdn) { + return{ query:"controllers.queries.supplier_query" } +} \ No newline at end of file diff --git a/stock/doctype/stock_entry/stock_entry.py b/stock/doctype/stock_entry/stock_entry.py index 217a0aad23c..0e05a882ff3 100644 --- a/stock/doctype/stock_entry/stock_entry.py +++ b/stock/doctype/stock_entry/stock_entry.py @@ -367,7 +367,8 @@ class DocType(StockController): def get_item_details(self, arg): arg = json.loads(arg) - item = webnotes.conn.sql("""select stock_uom, description, item_name from `tabItem` + item = webnotes.conn.sql("""select stock_uom, description, item_name, + purchase_account, cost_center from `tabItem` where name = %s and (ifnull(end_of_life,'')='' or end_of_life ='0000-00-00' or end_of_life > now())""", (arg.get('item_code')), as_dict = 1) if not item: @@ -378,6 +379,9 @@ class DocType(StockController): 'stock_uom' : item and item[0]['stock_uom'] or '', 'description' : item and item[0]['description'] or '', 'item_name' : item and item[0]['item_name'] or '', + 'expense_account' : item and item[0]['purchase_account'] or arg.get("expense_account") \ + or webnotes.conn.get_value("Company", arg.get("company"), "default_expense_account"), + 'cost_center' : item and item[0]['cost_center'] or arg.get("cost_center"), 'qty' : 0, 'transfer_qty' : 0, 'conversion_factor' : 1, diff --git a/stock/doctype/stock_entry_detail/stock_entry_detail.txt b/stock/doctype/stock_entry_detail/stock_entry_detail.txt index b400cdd2485..b7662506702 100644 --- a/stock/doctype/stock_entry_detail/stock_entry_detail.txt +++ b/stock/doctype/stock_entry_detail/stock_entry_detail.txt @@ -2,7 +2,7 @@ { "creation": "2013-03-29 18:22:12", "docstatus": 0, - "modified": "2013-08-28 19:25:38", + "modified": "2013-10-15 14:58:09", "modified_by": "Administrator", "owner": "Administrator" }, @@ -154,6 +154,7 @@ "print_hide": 1 }, { + "default": ":Company", "depends_on": "eval:sys_defaults.auto_accounting_for_stock", "doctype": "DocField", "fieldname": "cost_center", From d05a3b3b5c47778aba9316a3dcfdbff2fe011f36 Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Fri, 18 Oct 2013 12:28:18 +0530 Subject: [PATCH 185/200] [Rename] Delivery Note Packing Item -> Packed Item --- .../p06_rename_packing_list_doctype.py | 20 +++ stock/doctype/packed_item/__init__.py | 0 stock/doctype/packed_item/packed_item.py | 105 +++++++++++ stock/doctype/packed_item/packed_item.txt | 170 ++++++++++++++++++ 4 files changed, 295 insertions(+) create mode 100644 patches/october_2013/p06_rename_packing_list_doctype.py create mode 100644 stock/doctype/packed_item/__init__.py create mode 100644 stock/doctype/packed_item/packed_item.py create mode 100644 stock/doctype/packed_item/packed_item.txt diff --git a/patches/october_2013/p06_rename_packing_list_doctype.py b/patches/october_2013/p06_rename_packing_list_doctype.py new file mode 100644 index 00000000000..a7a11e460d7 --- /dev/null +++ b/patches/october_2013/p06_rename_packing_list_doctype.py @@ -0,0 +1,20 @@ +# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. +# License: GNU General Public License v3. See license.txt + +from __future__ import unicode_literals +import webnotes, os + +def execute(): + webnotes.reload_doc("core", "doctype", "doctype") + + tables = webnotes.conn.sql_list("show tables") + + if "tabPacked Item" not in tables: + webnotes.rename_doc("DocType", "Delivery Note Packing Item", "Packed Item", force=True) + + webnotes.reload_doc("stock", "doctype", "packed_item") + + os.system("rm -rf app/stock/doctype/delivery_note_packing_item") + + if webnotes.conn.exists("DocType", "Delivery Note Packing Item"): + webnotes.delete_doc("DocType", "Delivery Note Packing Item") \ No newline at end of file diff --git a/stock/doctype/packed_item/__init__.py b/stock/doctype/packed_item/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/stock/doctype/packed_item/packed_item.py b/stock/doctype/packed_item/packed_item.py new file mode 100644 index 00000000000..fc259585b6e --- /dev/null +++ b/stock/doctype/packed_item/packed_item.py @@ -0,0 +1,105 @@ +# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. +# MIT License. See license.txt + +# For license information, please see license.txt + +from __future__ import unicode_literals +import webnotes +from webnotes.utils import cstr, flt +from webnotes.model.doc import addchild +from webnotes.model.bean import getlist + +class DocType: + def __init__(self, d, dl): + self.doc, self.doclist = d, dl + +def get_sales_bom_items(item_code): + return webnotes.conn.sql("""select t1.item_code, t1.qty, t1.uom + from `tabSales BOM Item` t1, `tabSales BOM` t2 + where t2.new_item_code=%s and t1.parent = t2.name""", item_code, as_dict=1) + +def get_packing_item_details(item): + return webnotes.conn.sql("""select item_name, description, stock_uom from `tabItem` + where name = %s""", item, as_dict = 1)[0] + +def get_bin_qty(item, warehouse): + det = webnotes.conn.sql("""select actual_qty, projected_qty from `tabBin` + where item_code = %s and warehouse = %s""", (item, warehouse), as_dict = 1) + return det and det[0] or '' + +def update_packing_list_item(obj, packing_item_code, qty, warehouse, line, packing_list_idx): + bin = get_bin_qty(packing_item_code, warehouse) + item = get_packing_item_details(packing_item_code) + + # check if exists + exists = 0 + for d in getlist(obj.doclist, 'packing_details'): + if d.parent_item == line.item_code and d.item_code == packing_item_code and d.parent_detail_docname == line.name: + pi, exists = d, 1 + break + + if not exists: + pi = addchild(obj.doc, 'packing_details', 'Packed Item', obj.doclist) + + pi.parent_item = line.item_code + pi.item_code = packing_item_code + pi.item_name = item['item_name'] + pi.parent_detail_docname = line.name + pi.description = item['description'] + pi.uom = item['stock_uom'] + pi.qty = flt(qty) + pi.actual_qty = bin and flt(bin['actual_qty']) or 0 + pi.projected_qty = bin and flt(bin['projected_qty']) or 0 + if not pi.warehouse: + pi.warehouse = warehouse + if not pi.batch_no: + pi.batch_no = cstr(line.batch_no) + pi.idx = packing_list_idx + + # saved, since this function is called on_update of delivery note + pi.save() + + packing_list_idx += 1 + + +def make_packing_list(obj, item_table_fieldname): + """make packing list for sales bom item""" + packing_list_idx = 0 + parent_items = [] + for d in obj.doclist.get({"parentfield": item_table_fieldname}): + warehouse = (item_table_fieldname == "sales_order_details") \ + and d.reserved_warehouse or d.warehouse + if webnotes.conn.get_value("Sales BOM", {"new_item_code": d.item_code}): + for i in get_sales_bom_items(d.item_code): + update_packing_list_item(obj, i['item_code'], flt(i['qty'])*flt(d.qty), + warehouse, d, packing_list_idx) + + if [d.item_code, d.name] not in parent_items: + parent_items.append([d.item_code, d.name]) + + obj.doclist = cleanup_packing_list(obj, parent_items) + + return obj.doclist + +def cleanup_packing_list(obj, parent_items): + """Remove all those child items which are no longer present in main item table""" + delete_list = [] + for d in obj.doclist.get({"parentfield": "packing_details"}): + if [d.parent_item, d.parent_detail_docname] not in parent_items: + # mark for deletion from doclist + delete_list.append(d.name) + + if not delete_list: + return obj.doclist + + # delete from doclist + obj.doclist = webnotes.doclist(filter(lambda d: d.name not in delete_list, obj.doclist)) + + # delete from db + webnotes.conn.sql("""\ + delete from `tabPacked Item` + where name in (%s)""" + % (", ".join(["%s"] * len(delete_list))), + tuple(delete_list)) + + return obj.doclist \ No newline at end of file diff --git a/stock/doctype/packed_item/packed_item.txt b/stock/doctype/packed_item/packed_item.txt new file mode 100644 index 00000000000..8320502cf76 --- /dev/null +++ b/stock/doctype/packed_item/packed_item.txt @@ -0,0 +1,170 @@ +[ + { + "creation": "2013-02-22 01:28:00", + "docstatus": 0, + "modified": "2013-10-16 16:37:31", + "modified_by": "Administrator", + "owner": "Administrator" + }, + { + "doctype": "DocType", + "istable": 1, + "module": "Stock", + "name": "__common__" + }, + { + "doctype": "DocField", + "name": "__common__", + "parent": "Packed Item", + "parentfield": "fields", + "parenttype": "DocType", + "permlevel": 0 + }, + { + "doctype": "DocType", + "name": "Packed Item" + }, + { + "doctype": "DocField", + "fieldname": "parent_item", + "fieldtype": "Link", + "in_list_view": 1, + "label": "Parent Item", + "oldfieldname": "parent_item", + "oldfieldtype": "Link", + "options": "Item", + "read_only": 1 + }, + { + "doctype": "DocField", + "fieldname": "item_code", + "fieldtype": "Link", + "in_filter": 1, + "in_list_view": 1, + "label": "Item Code", + "oldfieldname": "item_code", + "oldfieldtype": "Link", + "options": "Item", + "read_only": 1 + }, + { + "doctype": "DocField", + "fieldname": "item_name", + "fieldtype": "Data", + "in_filter": 1, + "in_list_view": 1, + "label": "Item Name", + "oldfieldname": "item_name", + "oldfieldtype": "Data", + "read_only": 1 + }, + { + "doctype": "DocField", + "fieldname": "parent_detail_docname", + "fieldtype": "Data", + "hidden": 1, + "in_list_view": 0, + "label": "Parent Detail docname", + "no_copy": 1, + "oldfieldname": "parent_detail_docname", + "oldfieldtype": "Data", + "print_hide": 1, + "read_only": 1 + }, + { + "doctype": "DocField", + "fieldname": "description", + "fieldtype": "Text", + "in_list_view": 1, + "label": "Description", + "oldfieldname": "description", + "oldfieldtype": "Text", + "print_width": "300px", + "read_only": 1, + "width": "300px" + }, + { + "doctype": "DocField", + "fieldname": "warehouse", + "fieldtype": "Link", + "in_list_view": 1, + "label": "Warehouse", + "oldfieldname": "warehouse", + "oldfieldtype": "Link", + "options": "Warehouse" + }, + { + "doctype": "DocField", + "fieldname": "qty", + "fieldtype": "Float", + "in_list_view": 1, + "label": "Qty", + "oldfieldname": "qty", + "oldfieldtype": "Currency", + "read_only": 1 + }, + { + "doctype": "DocField", + "fieldname": "serial_no", + "fieldtype": "Text", + "label": "Serial No" + }, + { + "doctype": "DocField", + "fieldname": "batch_no", + "fieldtype": "Data", + "label": "Batch No" + }, + { + "doctype": "DocField", + "fieldname": "actual_qty", + "fieldtype": "Float", + "label": "Actual Qty", + "no_copy": 1, + "oldfieldname": "actual_qty", + "oldfieldtype": "Currency", + "read_only": 1 + }, + { + "doctype": "DocField", + "fieldname": "projected_qty", + "fieldtype": "Float", + "label": "Projected Qty", + "no_copy": 1, + "oldfieldname": "projected_qty", + "oldfieldtype": "Currency", + "read_only": 1 + }, + { + "doctype": "DocField", + "fieldname": "uom", + "fieldtype": "Link", + "label": "UOM", + "oldfieldname": "uom", + "oldfieldtype": "Link", + "options": "UOM", + "read_only": 1, + "search_index": 0 + }, + { + "doctype": "DocField", + "fieldname": "prevdoc_doctype", + "fieldtype": "Data", + "hidden": 1, + "label": "Prevdoc DocType", + "oldfieldname": "prevdoc_doctype", + "oldfieldtype": "Data", + "print_hide": 1, + "read_only": 1 + }, + { + "allow_on_submit": 1, + "doctype": "DocField", + "fieldname": "page_break", + "fieldtype": "Check", + "label": "Page Break", + "oldfieldname": "page_break", + "oldfieldtype": "Check", + "read_only": 1 + } +] \ No newline at end of file From d1fd1e2d89ace75e0dc6a19c8ecf4b7ffffa3c2b Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Fri, 18 Oct 2013 12:29:11 +0530 Subject: [PATCH 186/200] [Cleanup] Sales Common deprecated --- .../doctype/sales_invoice/sales_invoice.js | 2 +- .../doctype/sales_invoice/sales_invoice.py | 34 +- controllers/queries.py | 34 +- controllers/selling_controller.py | 124 ++++++- controllers/stock_controller.py | 1 - .../production_planning_tool.py | 4 +- ...ate_delivered_billed_percentage_for_pos.py | 7 +- patches/patch_list.py | 2 + .../installation_note/installation_note.py | 6 +- selling/doctype/opportunity/opportunity.py | 10 - selling/doctype/quotation/quotation.js | 2 +- selling/doctype/quotation/quotation.py | 48 +-- selling/doctype/sales_common/README.md | 1 - selling/doctype/sales_common/__init__.py | 1 - selling/doctype/sales_common/sales_common.py | 317 ------------------ selling/doctype/sales_common/sales_common.txt | 19 -- selling/doctype/sales_order/sales_order.js | 2 +- selling/doctype/sales_order/sales_order.py | 41 +-- selling/doctype/sales_order/sales_order.txt | 2 +- .../sales_common => }/sales_common.js | 28 +- stock/doctype/delivery_note/delivery_note.js | 9 +- stock/doctype/delivery_note/delivery_note.py | 39 +-- stock/doctype/delivery_note/delivery_note.txt | 2 +- .../delivery_note_packing_item/README.md | 1 - .../delivery_note_packing_item/__init__.py | 1 - .../delivery_note_packing_item.py | 9 - .../delivery_note_packing_item.txt | 170 ---------- translations/ar.csv | 2 +- translations/de.csv | 2 +- translations/el.csv | 2 +- translations/es.csv | 2 +- translations/fr.csv | 2 +- translations/hi.csv | 2 +- translations/hr.csv | 2 +- translations/it.csv | 2 +- translations/nl.csv | 2 +- translations/pt-BR.csv | 2 +- translations/pt.csv | 2 +- translations/sr.csv | 2 +- translations/ta.csv | 2 +- translations/th.csv | 2 +- utilities/repost_stock.py | 2 +- 42 files changed, 219 insertions(+), 727 deletions(-) delete mode 100644 selling/doctype/sales_common/README.md delete mode 100644 selling/doctype/sales_common/__init__.py delete mode 100644 selling/doctype/sales_common/sales_common.py delete mode 100644 selling/doctype/sales_common/sales_common.txt rename selling/{doctype/sales_common => }/sales_common.js (97%) delete mode 100644 stock/doctype/delivery_note_packing_item/README.md delete mode 100644 stock/doctype/delivery_note_packing_item/__init__.py delete mode 100644 stock/doctype/delivery_note_packing_item/delivery_note_packing_item.py delete mode 100644 stock/doctype/delivery_note_packing_item/delivery_note_packing_item.txt diff --git a/accounts/doctype/sales_invoice/sales_invoice.js b/accounts/doctype/sales_invoice/sales_invoice.js index 6f35f92fb22..19d27165a0d 100644 --- a/accounts/doctype/sales_invoice/sales_invoice.js +++ b/accounts/doctype/sales_invoice/sales_invoice.js @@ -11,7 +11,7 @@ cur_frm.pformat.print_heading = 'Invoice'; wn.require('app/accounts/doctype/sales_taxes_and_charges_master/sales_taxes_and_charges_master.js'); wn.require('app/utilities/doctype/sms_control/sms_control.js'); -wn.require('app/selling/doctype/sales_common/sales_common.js'); +wn.require('app/selling/sales_common.js'); wn.require('app/accounts/doctype/sales_invoice/pos.js'); wn.provide("erpnext.accounts"); diff --git a/accounts/doctype/sales_invoice/sales_invoice.py b/accounts/doctype/sales_invoice/sales_invoice.py index b6548c05984..cdae74eac49 100644 --- a/accounts/doctype/sales_invoice/sales_invoice.py +++ b/accounts/doctype/sales_invoice/sales_invoice.py @@ -48,11 +48,7 @@ class DocType(SellingController): self.validate_proj_cust() self.validate_with_previous_doc() self.validate_uom_is_integer("stock_uom", "qty") - - sales_com_obj = get_obj('Sales Common') - sales_com_obj.check_stop_sales_order(self) - sales_com_obj.check_active_sales_items(self) - sales_com_obj.validate_max_discount(self, 'entries') + self.check_stop_sales_order("sales_order") self.validate_customer_account() self.validate_debit_acc() self.validate_fixed_asset_account() @@ -110,8 +106,7 @@ class DocType(SellingController): if cint(self.doc.update_stock) == 1: self.update_stock_ledger() - sales_com_obj = get_obj(dt = 'Sales Common') - sales_com_obj.check_stop_sales_order(self) + self.check_stop_sales_order("sales_order") from accounts.utils import remove_against_link_from_jv remove_against_link_from_jv(self.doc.doctype, self.doc.name, "against_invoice") @@ -255,19 +250,7 @@ class DocType(SellingController): else: due_date = self.doc.posting_date - return due_date - - def get_barcode_details(self, barcode): - return get_obj('Sales Common').get_barcode_details(barcode) - - - def get_adj_percent(self, arg=''): - """Fetch ref rate from item master as per selected price list""" - get_obj('Sales Common').get_adj_percent(self) - - def get_comm_rate(self, sales_partner): - """Get Commission rate of Sales Partner""" - return get_obj('Sales Common').get_comm_rate(sales_partner, self) + return due_date def get_advances(self): super(DocType, self).get_advances(self.doc.debit_to, @@ -470,10 +453,6 @@ class DocType(SellingController): w = ps[0][1] return w - - def make_packing_list(self): - get_obj('Sales Common').make_packing_list(self,'entries') - def on_update(self): if cint(self.doc.update_stock) == 1: # Set default warehouse from pos setting @@ -484,7 +463,8 @@ class DocType(SellingController): if not d.warehouse: d.warehouse = cstr(w) - self.make_packing_list() + from stock.doctype.packed_item.packed_item import make_packing_list + make_packing_list(self, 'entries') else: self.doclist = self.doc.clear_table(self.doclist, 'packing_details') @@ -516,8 +496,7 @@ class DocType(SellingController): def update_stock_ledger(self): sl_entries = [] - items = get_obj('Sales Common').get_item_list(self) - for d in items: + for d in self.get_item_list(): if webnotes.conn.get_value("Item", d.item_code, "is_stock_item") == "Yes" \ and d.warehouse: sl_entries.append(self.get_sl_entries(d, { @@ -860,7 +839,6 @@ def send_notification(new_rv): def notify_errors(inv, owner): import webnotes - import website exception_msg = """ Dear User, diff --git a/controllers/queries.py b/controllers/queries.py index 637d5e18cd8..ed44f9b02dd 100644 --- a/controllers/queries.py +++ b/controllers/queries.py @@ -174,4 +174,36 @@ def get_delivery_notes_to_be_billed(doctype, txt, searchfield, start, page_len, "fcond": get_filters_cond(doctype, filters, []), "mcond": get_match_cond(doctype), "start": "%(start)s", "page_len": "%(page_len)s", "txt": "%(txt)s" - }, { "start": start, "page_len": page_len, "txt": ("%%%s%%" % txt) }) \ No newline at end of file + }, { "start": start, "page_len": page_len, "txt": ("%%%s%%" % txt) }) + +def get_batch_no(doctype, txt, searchfield, start, page_len, filters): + from controllers.queries import get_match_cond + + if filters.has_key('warehouse'): + return webnotes.conn.sql("""select batch_no from `tabStock Ledger Entry` sle + where item_code = '%(item_code)s' + and warehouse = '%(warehouse)s' + and batch_no like '%(txt)s' + and exists(select * from `tabBatch` + where name = sle.batch_no + and (ifnull(expiry_date, '')='' or expiry_date >= '%(posting_date)s') + and docstatus != 2) + %(mcond)s + group by batch_no having sum(actual_qty) > 0 + order by batch_no desc + limit %(start)s, %(page_len)s """ % {'item_code': filters['item_code'], + 'warehouse': filters['warehouse'], 'posting_date': filters['posting_date'], + 'txt': "%%%s%%" % txt, 'mcond':get_match_cond(doctype, searchfield), + 'start': start, 'page_len': page_len}) + else: + return webnotes.conn.sql("""select name from tabBatch + where docstatus != 2 + and item = '%(item_code)s' + and (ifnull(expiry_date, '')='' or expiry_date >= '%(posting_date)s') + and name like '%(txt)s' + %(mcond)s + order by name desc + limit %(start)s, %(page_len)s""" % {'item_code': filters['item_code'], + 'posting_date': filters['posting_date'], 'txt': "%%%s%%" % txt, + 'mcond':get_match_cond(doctype, searchfield),'start': start, + 'page_len': page_len}) \ No newline at end of file diff --git a/controllers/selling_controller.py b/controllers/selling_controller.py index d78cf932b46..0215dbd39e3 100644 --- a/controllers/selling_controller.py +++ b/controllers/selling_controller.py @@ -3,7 +3,7 @@ from __future__ import unicode_literals import webnotes -from webnotes.utils import cint, flt, comma_or, _round, add_days, cstr +from webnotes.utils import cint, flt, comma_or, _round, cstr from setup.utils import get_company_currency from selling.utils import get_item_details from webnotes import msgprint, _ @@ -14,6 +14,11 @@ class SellingController(StockController): def onload_post_render(self): # contact, address, item details and pos details (if applicable) self.set_missing_values() + + def validate(self): + super(SellingController, self).validate() + self.validate_max_discount() + check_active_sales_items(self) def get_sender(self, comm): return webnotes.conn.get_value('Sales Email Settings', None, 'email_id') @@ -237,3 +242,120 @@ class SellingController(StockController): elif self.doc.order_type not in valid_types: msgprint(_(self.meta.get_label("order_type")) + " " + _("must be one of") + ": " + comma_or(valid_types), raise_exception=True) + + def check_credit(self, grand_total): + customer_account = webnotes.conn.get_value("Account", {"company": self.doc.company, + "master_name": self.doc.customer}, "name") + if customer_account: + total_outstanding = 0 + total_outstanding = webnotes.conn.sql("""select + sum(ifnull(debit, 0)) - sum(ifnull(credit, 0)) + from `tabGL Entry` where account = %s""", customer_account)[0][0] + + outstanding_including_current = flt(total_outstanding) + flt(grand_total) + webnotes.bean('Account', customer_account).run_method("check_credit_limit", + customer_account, self.doc.company, outstanding_including_current) + + def validate_max_discount(self): + for d in self.doclist.get({"parentfield": self.fname}): + discount = flt(webnotes.conn.get_value("Item", d.item_code, "max_discount")) + + if discount and flt(d.adj_rate) > discount: + webnotes.throw(_("You cannot give more than ") + cstr(discount) + "% " + + _("discount on Item Code") + ": " + cstr(d.item_code)) + + def get_item_list(self): + il = [] + for d in self.doclist.get({"parentfield": self.fname}): + reserved_warehouse = "" + reserved_qty_for_main_item = 0 + + if self.doc.doctype == "Sales Order": + if (webnotes.conn.get_value("Item", d.item_code, "is_stock_item") == 'Yes' or + self.has_sales_bom(d.item_code)) and not d.reserved_warehouse: + webnotes.throw(_("Please enter Reserved Warehouse for item ") + + d.item_code + _(" as it is stock Item or packing item")) + reserved_warehouse = d.reserved_warehouse + if flt(d.qty) > flt(d.delivered_qty): + reserved_qty_for_main_item = flt(d.qty) - flt(d.delivered_qty) + + if self.doc.doctype == "Delivery Note" and d.against_sales_order: + # if SO qty is 10 and there is tolerance of 20%, then it will allow DN of 12. + # But in this case reserved qty should only be reduced by 10 and not 12 + + already_delivered_qty = self.get_already_delivered_qty(self.doc.name, + d.against_sales_order, d.prevdoc_detail_docname) + so_qty, reserved_warehouse = self.get_so_qty_and_warehouse(d.prevdoc_detail_docname) + + if already_delivered_qty + d.qty > so_qty: + reserved_qty_for_main_item = -(so_qty - already_delivered_qty) + else: + reserved_qty_for_main_item = -flt(d.qty) + + if self.has_sales_bom(d.item_code): + for p in self.doclist.get({"parentfield": "packing_details"}): + if p.parent_detail_docname == d.name and p.parent_item == d.item_code: + # the packing details table's qty is already multiplied with parent's qty + il.append(webnotes._dict({ + 'warehouse': p.warehouse, + 'reserved_warehouse': reserved_warehouse, + 'item_code': p.item_code, + 'qty': flt(p.qty), + 'reserved_qty': (flt(p.qty)/flt(d.qty)) * reserved_qty_for_main_item, + 'uom': p.uom, + 'batch_no': cstr(p.batch_no).strip(), + 'serial_no': cstr(p.serial_no).strip(), + 'name': d.name + })) + else: + il.append(webnotes._dict({ + 'warehouse': d.warehouse, + 'reserved_warehouse': reserved_warehouse, + 'item_code': d.item_code, + 'qty': d.qty, + 'reserved_qty': reserved_qty_for_main_item, + 'uom': d.stock_uom, + 'batch_no': cstr(d.batch_no).strip(), + 'serial_no': cstr(d.serial_no).strip(), + 'name': d.name + })) + return il + + def has_sales_bom(self, item_code): + return webnotes.conn.sql("""select name from `tabSales BOM` + where new_item_code=%s and docstatus != 2""", item_code) + + def get_already_delivered_qty(self, dn, so, so_detail): + qty = webnotes.conn.sql("""select sum(qty) from `tabDelivery Note Item` + where prevdoc_detail_docname = %s and docstatus = 1 + and against_sales_order = %s + and parent != %s""", (so_detail, so, dn)) + return qty and flt(qty[0][0]) or 0.0 + + def get_so_qty_and_warehouse(self, so_detail): + so_item = webnotes.conn.sql("""select qty, reserved_warehouse from `tabSales Order Item` + where name = %s and docstatus = 1""", so_detail, as_dict=1) + so_qty = so_item and flt(so_item[0]["qty"]) or 0.0 + so_warehouse = so_item and so_item[0]["reserved_warehouse"] or "" + return so_qty, so_warehouse + + def check_stop_sales_order(self, ref_fieldname): + for d in self.doclist.get({"parentfield": self.fname}): + if d.fields.get(ref_fieldname): + status = webnotes.conn.get_value("Sales Order", d.fields[ref_fieldname], "status") + if status == "Stopped": + webnotes.throw(self.doc.doctype + + _(" can not be created/modified against stopped Sales Order ") + + d.fields[ref_fieldname]) + +def check_active_sales_items(obj): + for d in obj.doclist.get({"parentfield": obj.fname}): + if d.item_code: + item = webnotes.conn.sql("""select docstatus, is_sales_item, + is_service_item, default_income_account from tabItem where name = %s""", + d.item_code, as_dict=True)[0] + if item.is_sales_item == 'No' and item.is_service_item == 'No': + webnotes.throw(_("Item is neither Sales nor Service Item") + ": " + d.item_code) + if d.income_account and not item.default_income_account: + webnotes.conn.set_value("Item", d.item_code, "default_income_account", + d.income_account) \ No newline at end of file diff --git a/controllers/stock_controller.py b/controllers/stock_controller.py index d4c92a90a7e..7d5d0456daa 100644 --- a/controllers/stock_controller.py +++ b/controllers/stock_controller.py @@ -99,7 +99,6 @@ class StockController(AccountsController): return warehouse_account def update_gl_entries_after(self, warehouse_account=None): - from accounts.utils import get_stock_and_account_difference future_stock_vouchers = self.get_future_stock_vouchers() gle = self.get_voucherwise_gl_entries(future_stock_vouchers) if not warehouse_account: diff --git a/manufacturing/doctype/production_planning_tool/production_planning_tool.py b/manufacturing/doctype/production_planning_tool/production_planning_tool.py index 6f15d4c9f10..277e53a7bf9 100644 --- a/manufacturing/doctype/production_planning_tool/production_planning_tool.py +++ b/manufacturing/doctype/production_planning_tool/production_planning_tool.py @@ -72,7 +72,7 @@ class DocType: and (exists (select name from `tabItem` item where item.name=so_item.item_code and (ifnull(item.is_pro_applicable, 'No') = 'Yes' or ifnull(item.is_sub_contracted_item, 'No') = 'Yes') %s) - or exists (select name from `tabDelivery Note Packing Item` dnpi + or exists (select name from `tabPacked Item` dnpi where dnpi.parent = so.name and dnpi.parent_item = so_item.item_code and exists (select name from `tabItem` item where item.name=dnpi.item_code and (ifnull(item.is_pro_applicable, 'No') = 'Yes' @@ -119,7 +119,7 @@ class DocType: dnpi_items = webnotes.conn.sql("""select distinct dnpi.parent, dnpi.item_code, dnpi.warehouse as reserved_warhouse, (((so_item.qty - ifnull(so_item.delivered_qty, 0)) * dnpi.qty) / so_item.qty) as pending_qty - from `tabSales Order Item` so_item, `tabDelivery Note Packing Item` dnpi + from `tabSales Order Item` so_item, `tabPacked Item` dnpi where so_item.parent = dnpi.parent and so_item.docstatus = 1 and dnpi.parent_item = so_item.item_code and so_item.parent in (%s) and ifnull(so_item.qty, 0) > ifnull(so_item.delivered_qty, 0) diff --git a/patches/november_2012/update_delivered_billed_percentage_for_pos.py b/patches/november_2012/update_delivered_billed_percentage_for_pos.py index 0703f946f38..ffba0f98e85 100644 --- a/patches/november_2012/update_delivered_billed_percentage_for_pos.py +++ b/patches/november_2012/update_delivered_billed_percentage_for_pos.py @@ -3,10 +3,6 @@ def execute(): import webnotes - from webnotes.model.code import get_obj - - #sc_obj = get_obj("Sales Common") - from selling.doctype.sales_common import sales_common si = webnotes.conn.sql("""select distinct si.name from `tabSales Invoice` si, `tabSales Invoice Item` si_item @@ -16,5 +12,4 @@ def execute(): and ifnull(si_item.sales_order, '') != '' """) for d in si: - sales_common.StatusUpdater(get_obj("Sales Invoice", d[0], with_children=1), \ - 1).update_all_qty() \ No newline at end of file + webnotes.bean("Sales Invoice", d[0]).run_method("update_qty") \ No newline at end of file diff --git a/patches/patch_list.py b/patches/patch_list.py index 9851986415b..78dc155307b 100644 --- a/patches/patch_list.py +++ b/patches/patch_list.py @@ -226,4 +226,6 @@ patch_list = [ "patches.october_2013.p05_server_custom_script_to_file", "patches.october_2013.repost_ordered_qty", "patches.october_2013.repost_planned_qty", + "patches.october_2013.p06_rename_packing_list_doctype", + "execute:webnotes.delete_doc('DocType', 'Sales Common')", ] \ No newline at end of file diff --git a/selling/doctype/installation_note/installation_note.py b/selling/doctype/installation_note/installation_note.py index 02b724719c1..17c36919e53 100644 --- a/selling/doctype/installation_note/installation_note.py +++ b/selling/doctype/installation_note/installation_note.py @@ -6,7 +6,6 @@ import webnotes from webnotes.utils import cstr, getdate from webnotes.model.bean import getlist -from webnotes.model.code import get_obj from webnotes import msgprint from stock.utils import get_valid_serial_nos @@ -36,8 +35,9 @@ class DocType(TransactionBase): self.validate_fiscal_year() self.validate_installation_date() self.check_item_table() - sales_com_obj = get_obj(dt = 'Sales Common') - sales_com_obj.check_active_sales_items(self) + + from controllers.selling_controller import check_active_sales_items + check_active_sales_items(self) def validate_fiscal_year(self): from accounts.utils import validate_fiscal_year diff --git a/selling/doctype/opportunity/opportunity.py b/selling/doctype/opportunity/opportunity.py index 37672f2afb2..ecba077515c 100644 --- a/selling/doctype/opportunity/opportunity.py +++ b/selling/doctype/opportunity/opportunity.py @@ -59,16 +59,6 @@ class DocType(TransactionBase): msgprint("Customer : %s does not exist in system." % (name)) raise Exception - def get_contact_details(self, arg): - arg = eval(arg) - contact = webnotes.conn.sql("select contact_no, email_id from `tabContact` where contact_name = '%s' and customer_name = '%s'" %(arg['contact_person'],arg['customer']), as_dict = 1) - ret = { - 'contact_no' : contact and contact[0]['contact_no'] or '', - 'email_id' : contact and contact[0]['email_id'] or '' - } - return ret - - def on_update(self): self.add_calendar_event() diff --git a/selling/doctype/quotation/quotation.js b/selling/doctype/quotation/quotation.js index 05feed012bb..4c27d523bca 100644 --- a/selling/doctype/quotation/quotation.js +++ b/selling/doctype/quotation/quotation.js @@ -10,7 +10,7 @@ cur_frm.cscript.sales_team_fname = "sales_team"; wn.require('app/accounts/doctype/sales_taxes_and_charges_master/sales_taxes_and_charges_master.js'); wn.require('app/utilities/doctype/sms_control/sms_control.js'); -wn.require('app/selling/doctype/sales_common/sales_common.js'); +wn.require('app/selling/sales_common.js'); wn.require('app/accounts/doctype/sales_invoice/pos.js'); erpnext.selling.QuotationController = erpnext.selling.SellingController.extend({ diff --git a/selling/doctype/quotation/quotation.py b/selling/doctype/quotation/quotation.py index bd158d580af..cf82407485d 100644 --- a/selling/doctype/quotation/quotation.py +++ b/selling/doctype/quotation/quotation.py @@ -19,46 +19,10 @@ class DocType(SellingController): self.doclist = doclist self.tname = 'Quotation Item' self.fname = 'quotation_details' - - # Get contact person details based on customer selected - # ------------------------------------------------------ - def get_contact_details(self): - return get_obj('Sales Common').get_contact_details(self,0) - - # Get Item Details - # ----------------- - def get_item_details(self, args=None): - import json - args = args and json.loads(args) or {} - if args.get('item_code'): - return get_obj('Sales Common').get_item_details(args, self) - else: - obj = get_obj('Sales Common') - for doc in self.doclist: - if doc.fields.get('item_code'): - arg = { - 'item_code': doc.fields.get('item_code'), - 'income_account': doc.fields.get('income_account'), - 'cost_center': doc.fields.get('cost_center'), - 'warehouse': doc.fields.get('warehouse') - } - res = obj.get_item_details(arg, self) or {} - for r in res: - if not doc.fields.get(r): - doc.fields[r] = res[r] - def has_sales_order(self): return webnotes.conn.get_value("Sales Order Item", {"prevdoc_docname": self.doc.name, "docstatus": 1}) - - - # Re-calculates Basic Rate & amount based on Price List Selected - # -------------------------------------------------------------- - def get_adj_percent(self, arg=''): - get_obj('Sales Common').get_adj_percent(self) - - # Does not allow same item code to be entered twice - # ------------------------------------------------- + def validate_for_items(self): chk_dupl_itm = [] for d in getlist(self.doclist,'quotation_details'): @@ -68,9 +32,6 @@ class DocType(SellingController): else: chk_dupl_itm.append([cstr(d.item_code),cstr(d.description)]) - - #do not allow sales item in maintenance quotation and service item in sales quotation - #----------------------------------------------------------------------------------------------- def validate_order_type(self): super(DocType, self).validate_order_type() @@ -96,15 +57,8 @@ class DocType(SellingController): self.set_status() self.validate_order_type() self.validate_for_items() - self.validate_uom_is_integer("stock_uom", "qty") - sales_com_obj = get_obj('Sales Common') - sales_com_obj.check_active_sales_items(self) - sales_com_obj.validate_max_discount(self,'quotation_details') - - #update enquiry - #------------------ def update_opportunity(self): for opportunity in self.doclist.get_distinct_values("prevdoc_docname"): webnotes.bean("Opportunity", opportunity).get_controller().set_status(update=True) diff --git a/selling/doctype/sales_common/README.md b/selling/doctype/sales_common/README.md deleted file mode 100644 index 1c029d250bd..00000000000 --- a/selling/doctype/sales_common/README.md +++ /dev/null @@ -1 +0,0 @@ -Common scripts used in Sales Cycle. \ No newline at end of file diff --git a/selling/doctype/sales_common/__init__.py b/selling/doctype/sales_common/__init__.py deleted file mode 100644 index baffc488252..00000000000 --- a/selling/doctype/sales_common/__init__.py +++ /dev/null @@ -1 +0,0 @@ -from __future__ import unicode_literals diff --git a/selling/doctype/sales_common/sales_common.py b/selling/doctype/sales_common/sales_common.py deleted file mode 100644 index e1172eb5660..00000000000 --- a/selling/doctype/sales_common/sales_common.py +++ /dev/null @@ -1,317 +0,0 @@ -# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. -# License: GNU General Public License v3. See license.txt - -from __future__ import unicode_literals -import webnotes - -from webnotes.utils import cint, cstr, flt -from webnotes.model.doc import addchild -from webnotes.model.bean import getlist -from webnotes.model.code import get_obj -from webnotes import msgprint, _ - -get_value = webnotes.conn.get_value - -from utilities.transaction_base import TransactionBase - -class DocType(TransactionBase): - def __init__(self,d,dl): - self.doc, self.doclist = d, dl - - - def get_contact_details(self, obj = '', primary = 0): - cond = " and contact_name = '"+cstr(obj.doc.contact_person)+"'" - if primary: cond = " and is_primary_contact = 'Yes'" - contact = webnotes.conn.sql("select contact_name, contact_no, email_id, contact_address from `tabContact` where customer = '%s' and docstatus != 2 %s" %(obj.doc.customer, cond), as_dict = 1) - if not contact: - return - c = contact[0] - obj.doc.contact_person = c['contact_name'] or '' - obj.doc.contact_no = c['contact_no'] or '' - obj.doc.email_id = c['email_id'] or '' - obj.doc.customer_mobile_no = c['contact_no'] or '' - if c['contact_address']: - obj.doc.customer_address = c['contact_address'] - - def get_invoice_details(self, obj = ''): - if obj.doc.company: - acc_head = webnotes.conn.sql("select name from `tabAccount` where name = '%s' and docstatus != 2" % (cstr(obj.doc.customer) + " - " + webnotes.conn.get_value('Company', obj.doc.company, 'abbr'))) - obj.doc.debit_to = acc_head and acc_head[0][0] or '' - - def get_tax_details(self, item_code, obj): - import json - tax = webnotes.conn.sql("select tax_type, tax_rate from `tabItem Tax` where parent = %s" , item_code) - t = {} - for x in tax: t[x[0]] = flt(x[1]) - ret = { - 'item_tax_rate' : tax and json.dumps(t) or '' - } - return ret - - def get_serial_details(self, serial_no, obj): - import json - item = webnotes.conn.sql("select item_code, make, label,brand, description from `tabSerial No` where name = '%s' and docstatus != 2" %(serial_no), as_dict=1) - tax = webnotes.conn.sql("select tax_type, tax_rate from `tabItem Tax` where parent = %s" , item[0]['item_code']) - t = {} - for x in tax: t[x[0]] = flt(x[1]) - ret = { - 'item_code' : item and item[0]['item_code'] or '', - 'make' : item and item[0]['make'] or '', - 'label' : item and item[0]['label'] or '', - 'brand' : item and item[0]['brand'] or '', - 'description' : item and item[0]['description'] or '', - 'item_tax_rate' : json.dumps(t) - } - return ret - - # To verify whether rate entered in details table does not exceed max discount % - # ======================================================================================= - def validate_max_discount(self,obj, detail_table): - for d in getlist(obj.doclist, detail_table): - discount = webnotes.conn.sql("select max_discount from tabItem where name = '%s'" %(d.item_code),as_dict = 1) - if discount and discount[0]['max_discount'] and (flt(d.adj_rate)>flt(discount[0]['max_discount'])): - msgprint("You cannot give more than " + cstr(discount[0]['max_discount']) + " % discount on Item Code : "+cstr(d.item_code)) - raise Exception - - def get_item_list(self, obj, is_stopped=0): - """get item list""" - il = [] - for d in getlist(obj.doclist, obj.fname): - reserved_warehouse = "" - reserved_qty_for_main_item = 0 - - if obj.doc.doctype == "Sales Order": - if (webnotes.conn.get_value("Item", d.item_code, "is_stock_item") == 'Yes' or - self.has_sales_bom(d.item_code)) and not d.reserved_warehouse: - webnotes.throw(_("Please enter Reserved Warehouse for item ") + - d.item_code + _(" as it is stock Item or packing item")) - reserved_warehouse = d.reserved_warehouse - if flt(d.qty) > flt(d.delivered_qty): - reserved_qty_for_main_item = flt(d.qty) - flt(d.delivered_qty) - - if obj.doc.doctype == "Delivery Note" and d.against_sales_order: - # if SO qty is 10 and there is tolerance of 20%, then it will allow DN of 12. - # But in this case reserved qty should only be reduced by 10 and not 12 - - already_delivered_qty = self.get_already_delivered_qty(obj.doc.name, - d.against_sales_order, d.prevdoc_detail_docname) - so_qty, reserved_warehouse = self.get_so_qty_and_warehouse(d.prevdoc_detail_docname) - - if already_delivered_qty + d.qty > so_qty: - reserved_qty_for_main_item = -(so_qty - already_delivered_qty) - else: - reserved_qty_for_main_item = -flt(d.qty) - - if self.has_sales_bom(d.item_code): - for p in getlist(obj.doclist, 'packing_details'): - if p.parent_detail_docname == d.name and p.parent_item == d.item_code: - # the packing details table's qty is already multiplied with parent's qty - il.append(webnotes._dict({ - 'warehouse': p.warehouse, - 'reserved_warehouse': reserved_warehouse, - 'item_code': p.item_code, - 'qty': flt(p.qty), - 'reserved_qty': (flt(p.qty)/flt(d.qty)) * reserved_qty_for_main_item, - 'uom': p.uom, - 'batch_no': cstr(p.batch_no).strip(), - 'serial_no': cstr(p.serial_no).strip(), - 'name': d.name - })) - else: - il.append(webnotes._dict({ - 'warehouse': d.warehouse, - 'reserved_warehouse': reserved_warehouse, - 'item_code': d.item_code, - 'qty': d.qty, - 'reserved_qty': reserved_qty_for_main_item, - 'uom': d.stock_uom, - 'batch_no': cstr(d.batch_no).strip(), - 'serial_no': cstr(d.serial_no).strip(), - 'name': d.name - })) - return il - - def get_already_delivered_qty(self, dn, so, so_detail): - qty = webnotes.conn.sql("""select sum(qty) from `tabDelivery Note Item` - where prevdoc_detail_docname = %s and docstatus = 1 - and against_sales_order = %s - and parent != %s""", (so_detail, so, dn)) - return qty and flt(qty[0][0]) or 0.0 - - def get_so_qty_and_warehouse(self, so_detail): - so_item = webnotes.conn.sql("""select qty, reserved_warehouse from `tabSales Order Item` - where name = %s and docstatus = 1""", so_detail, as_dict=1) - so_qty = so_item and flt(so_item[0]["qty"]) or 0.0 - so_warehouse = so_item and so_item[0]["reserved_warehouse"] or "" - return so_qty, so_warehouse - - def has_sales_bom(self, item_code): - return webnotes.conn.sql("select name from `tabSales BOM` where new_item_code=%s and docstatus != 2", item_code) - - def get_sales_bom_items(self, item_code): - return webnotes.conn.sql("""select t1.item_code, t1.qty, t1.uom - from `tabSales BOM Item` t1, `tabSales BOM` t2 - where t2.new_item_code=%s and t1.parent = t2.name""", item_code, as_dict=1) - - def get_packing_item_details(self, item): - return webnotes.conn.sql("select item_name, description, stock_uom from `tabItem` where name = %s", item, as_dict = 1)[0] - - def get_bin_qty(self, item, warehouse): - det = webnotes.conn.sql("select actual_qty, projected_qty from `tabBin` where item_code = '%s' and warehouse = '%s'" % (item, warehouse), as_dict = 1) - return det and det[0] or '' - - def update_packing_list_item(self,obj, packing_item_code, qty, warehouse, line): - bin = self.get_bin_qty(packing_item_code, warehouse) - item = self.get_packing_item_details(packing_item_code) - - # check if exists - exists = 0 - for d in getlist(obj.doclist, 'packing_details'): - if d.parent_item == line.item_code and d.item_code == packing_item_code and d.parent_detail_docname == line.name: - pi, exists = d, 1 - break - - if not exists: - pi = addchild(obj.doc, 'packing_details', 'Delivery Note Packing Item', - obj.doclist) - - pi.parent_item = line.item_code - pi.item_code = packing_item_code - pi.item_name = item['item_name'] - pi.parent_detail_docname = line.name - pi.description = item['description'] - pi.uom = item['stock_uom'] - pi.qty = flt(qty) - pi.actual_qty = bin and flt(bin['actual_qty']) or 0 - pi.projected_qty = bin and flt(bin['projected_qty']) or 0 - if not pi.warehouse: - pi.warehouse = warehouse - if not pi.batch_no: - pi.batch_no = cstr(line.batch_no) - pi.idx = self.packing_list_idx - - # saved, since this function is called on_update of delivery note - pi.save() - - self.packing_list_idx += 1 - - - def make_packing_list(self, obj, fname): - """make packing list for sales bom item""" - self.packing_list_idx = 0 - parent_items = [] - for d in getlist(obj.doclist, fname): - warehouse = fname == "sales_order_details" and d.reserved_warehouse or d.warehouse - if self.has_sales_bom(d.item_code): - for i in self.get_sales_bom_items(d.item_code): - self.update_packing_list_item(obj, i['item_code'], flt(i['qty'])*flt(d.qty), warehouse, d) - - if [d.item_code, d.name] not in parent_items: - parent_items.append([d.item_code, d.name]) - - obj.doclist = self.cleanup_packing_list(obj, parent_items) - - return obj.doclist - - def cleanup_packing_list(self, obj, parent_items): - """Remove all those child items which are no longer present in main item table""" - delete_list = [] - for d in getlist(obj.doclist, 'packing_details'): - if [d.parent_item, d.parent_detail_docname] not in parent_items: - # mark for deletion from doclist - delete_list.append(d.name) - - if not delete_list: - return obj.doclist - - # delete from doclist - obj.doclist = webnotes.doclist(filter(lambda d: d.name not in delete_list, obj.doclist)) - - # delete from db - webnotes.conn.sql("""\ - delete from `tabDelivery Note Packing Item` - where name in (%s)""" - % (", ".join(["%s"] * len(delete_list))), - tuple(delete_list)) - - return obj.doclist - - - def get_month(self,date): - """Get month based on date (required in sales person and sales partner)""" - month_list = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'] - month_idx = cint(cstr(date).split('-')[1])-1 - return month_list[month_idx] - - - # **** Check for Stop SO as no transactions can be made against Stopped SO. Need to unstop it. *** - def check_stop_sales_order(self,obj): - for d in getlist(obj.doclist,obj.fname): - ref_doc_name = '' - if d.fields.has_key('against_sales_order') and d.against_sales_order: - ref_doc_name = d.against_sales_order - elif d.fields.has_key('sales_order') and d.sales_order and not d.delivery_note: - ref_doc_name = d.sales_order - if ref_doc_name: - so_status = webnotes.conn.sql("select status from `tabSales Order` where name = %s",ref_doc_name) - so_status = so_status and so_status[0][0] or '' - if so_status == 'Stopped': - msgprint("You cannot do any transaction against Sales Order : '%s' as it is Stopped." %(ref_doc_name)) - raise Exception - - def check_active_sales_items(self,obj): - for d in getlist(obj.doclist, obj.fname): - if d.item_code: - item = webnotes.conn.sql("""select docstatus, is_sales_item, - is_service_item, default_income_account from tabItem where name = %s""", - d.item_code, as_dict=True)[0] - if item.is_sales_item == 'No' and item.is_service_item == 'No': - msgprint("Item : '%s' is neither Sales nor Service Item" % (d.item_code)) - raise Exception - if d.income_account and not item.default_income_account: - webnotes.conn.set_value("Item", d.item_code, "default_income_account", d.income_account) - - - def check_credit(self,obj,grand_total): - acc_head = webnotes.conn.sql("select name from `tabAccount` where company = '%s' and master_name = '%s'"%(obj.doc.company, obj.doc.customer)) - if acc_head: - tot_outstanding = 0 - dbcr = webnotes.conn.sql("""select sum(debit), sum(credit) from `tabGL Entry` - where account = %s""", acc_head[0][0]) - if dbcr: - tot_outstanding = flt(dbcr[0][0])-flt(dbcr[0][1]) - - exact_outstanding = flt(tot_outstanding) + flt(grand_total) - get_obj('Account',acc_head[0][0]).check_credit_limit(acc_head[0][0], obj.doc.company, exact_outstanding) - -def get_batch_no(doctype, txt, searchfield, start, page_len, filters): - from controllers.queries import get_match_cond - - if filters.has_key('warehouse'): - return webnotes.conn.sql("""select batch_no from `tabStock Ledger Entry` sle - where item_code = '%(item_code)s' - and warehouse = '%(warehouse)s' - and batch_no like '%(txt)s' - and exists(select * from `tabBatch` - where name = sle.batch_no - and (ifnull(expiry_date, '')='' or expiry_date >= '%(posting_date)s') - and docstatus != 2) - %(mcond)s - group by batch_no having sum(actual_qty) > 0 - order by batch_no desc - limit %(start)s, %(page_len)s """ % {'item_code': filters['item_code'], - 'warehouse': filters['warehouse'], 'posting_date': filters['posting_date'], - 'txt': "%%%s%%" % txt, 'mcond':get_match_cond(doctype, searchfield), - 'start': start, 'page_len': page_len}) - else: - return webnotes.conn.sql("""select name from tabBatch - where docstatus != 2 - and item = '%(item_code)s' - and (ifnull(expiry_date, '')='' or expiry_date >= '%(posting_date)s') - and name like '%(txt)s' - %(mcond)s - order by name desc - limit %(start)s, %(page_len)s""" % {'item_code': filters['item_code'], - 'posting_date': filters['posting_date'], 'txt': "%%%s%%" % txt, - 'mcond':get_match_cond(doctype, searchfield),'start': start, - 'page_len': page_len}) diff --git a/selling/doctype/sales_common/sales_common.txt b/selling/doctype/sales_common/sales_common.txt deleted file mode 100644 index a407493c6f8..00000000000 --- a/selling/doctype/sales_common/sales_common.txt +++ /dev/null @@ -1,19 +0,0 @@ -[ - { - "creation": "2012-03-27 14:36:14", - "docstatus": 0, - "modified": "2013-07-10 14:54:19", - "modified_by": "Administrator", - "owner": "Administrator" - }, - { - "doctype": "DocType", - "issingle": 1, - "module": "Selling", - "name": "__common__" - }, - { - "doctype": "DocType", - "name": "Sales Common" - } -] \ No newline at end of file diff --git a/selling/doctype/sales_order/sales_order.js b/selling/doctype/sales_order/sales_order.js index bf23b9cb9df..4033870775a 100644 --- a/selling/doctype/sales_order/sales_order.js +++ b/selling/doctype/sales_order/sales_order.js @@ -9,7 +9,7 @@ cur_frm.cscript.other_fname = "other_charges"; cur_frm.cscript.sales_team_fname = "sales_team"; -wn.require('app/selling/doctype/sales_common/sales_common.js'); +wn.require('app/selling/sales_common.js'); wn.require('app/accounts/doctype/sales_taxes_and_charges_master/sales_taxes_and_charges_master.js'); wn.require('app/utilities/doctype/sms_control/sms_control.js'); wn.require('app/accounts/doctype/sales_invoice/pos.js'); diff --git a/selling/doctype/sales_order/sales_order.py b/selling/doctype/sales_order/sales_order.py index 6dfa3e2ec5b..a9ab8270d1d 100644 --- a/selling/doctype/sales_order/sales_order.py +++ b/selling/doctype/sales_order/sales_order.py @@ -11,8 +11,6 @@ from webnotes.model.code import get_obj from webnotes import msgprint from webnotes.model.mapper import get_mapped_doclist - - from controllers.selling_controller import SellingController class DocType(SellingController): @@ -26,18 +24,6 @@ class DocType(SellingController): self.partner_tname = 'Partner Target Detail' self.territory_tname = 'Territory Target Detail' - def get_contact_details(self): - get_obj('Sales Common').get_contact_details(self,0) - - def get_comm_rate(self, sales_partner): - return get_obj('Sales Common').get_comm_rate(sales_partner, self) - - def get_adj_percent(self, arg=''): - get_obj('Sales Common').get_adj_percent(self) - - def get_available_qty(self,args): - return get_obj('Sales Common').get_available_qty(eval(args)) - def validate_mandatory(self): # validate transaction date v/s delivery date if self.doc.delivery_date: @@ -124,12 +110,9 @@ class DocType(SellingController): self.validate_uom_is_integer("stock_uom", "qty") self.validate_for_items() self.validate_warehouse() - sales_com_obj = get_obj(dt = 'Sales Common') - sales_com_obj.check_active_sales_items(self) - - - sales_com_obj.validate_max_discount(self,'sales_order_details') - self.doclist = sales_com_obj.make_packing_list(self,'sales_order_details') + + from stock.doctype.packed_item.packed_item import make_packing_list + self.doclist = make_packing_list(self,'sales_order_details') self.validate_with_previous_doc() @@ -172,14 +155,14 @@ class DocType(SellingController): for quotation in self.doclist.get_distinct_values("prevdoc_docname"): bean = webnotes.bean("Quotation", quotation) if bean.doc.docstatus==2: - webnotes.throw(d.prevdoc_docname + ": " + webnotes._("Quotation is cancelled.")) + webnotes.throw(quotation + ": " + webnotes._("Quotation is cancelled.")) bean.get_controller().set_status(update=True) def on_submit(self): self.update_stock_ledger(update_stock = 1) - get_obj('Sales Common').check_credit(self,self.doc.grand_total) + self.check_credit(self.doc.grand_total) get_obj('Authorization Control').validate_approving_authority(self.doc.doctype, self.doc.grand_total, self) @@ -235,21 +218,21 @@ class DocType(SellingController): def stop_sales_order(self): self.check_modified_date() - self.update_stock_ledger(update_stock = -1,is_stopped = 1) + self.update_stock_ledger(-1) webnotes.conn.set(self.doc, 'status', 'Stopped') msgprint("""%s: %s has been Stopped. To make transactions against this Sales Order you need to Unstop it.""" % (self.doc.doctype, self.doc.name)) def unstop_sales_order(self): self.check_modified_date() - self.update_stock_ledger(update_stock = 1,is_stopped = 1) + self.update_stock_ledger(1) webnotes.conn.set(self.doc, 'status', 'Submitted') msgprint("%s: %s has been Unstopped" % (self.doc.doctype, self.doc.name)) - def update_stock_ledger(self, update_stock, is_stopped = 0): + def update_stock_ledger(self, update_stock): from stock.utils import update_bin - for d in self.get_item_list(is_stopped): + for d in self.get_item_list(): if webnotes.conn.get_value("Item", d['item_code'], "is_stock_item") == "Yes": args = { "item_code": d['item_code'], @@ -261,10 +244,6 @@ class DocType(SellingController): "is_amended": self.doc.amended_from and 'Yes' or 'No' } update_bin(args) - - - def get_item_list(self, is_stopped): - return get_obj('Sales Common').get_item_list( self, is_stopped) def on_update(self): pass @@ -438,4 +417,4 @@ def make_maintenance_visit(source_name, target_doclist=None): } }, target_doclist) - return [d.fields for d in doclist] + return [d.fields for d in doclist] \ No newline at end of file diff --git a/selling/doctype/sales_order/sales_order.txt b/selling/doctype/sales_order/sales_order.txt index c27f8ffa9de..bfbcd944609 100644 --- a/selling/doctype/sales_order/sales_order.txt +++ b/selling/doctype/sales_order/sales_order.txt @@ -361,7 +361,7 @@ "label": "Packing Details", "oldfieldname": "packing_details", "oldfieldtype": "Table", - "options": "Delivery Note Packing Item", + "options": "Packed Item", "print_hide": 1, "read_only": 1 }, diff --git a/selling/doctype/sales_common/sales_common.js b/selling/sales_common.js similarity index 97% rename from selling/doctype/sales_common/sales_common.js rename to selling/sales_common.js index f744faa32a6..ce6b7d6c64e 100644 --- a/selling/doctype/sales_common/sales_common.js +++ b/selling/sales_common.js @@ -73,23 +73,15 @@ erpnext.selling.SellingController = erpnext.TransactionController.extend({ if(!item.item_code) { wn.throw("Please enter Item Code to get batch no"); } else { - if(item.warehouse) { - return { - query : "selling.doctype.sales_common.sales_common.get_batch_no", - filters: { - 'item_code': item.item_code, - 'warehouse': item.warehouse, - 'posting_date': me.frm.doc.posting_date - } - } - } else { - return{ - query : "selling.doctype.sales_common.sales_common.get_batch_no", - filters: { - 'item_code': item.item_code, - 'posting_date': me.frm.doc.posting_date - } - } + filters = { + 'item_code': item.item_code, + 'posting_date': me.frm.doc.posting_date, + } + if(item.warehouse) filters["warehouse"] = item.warehouse + + return { + query : "controllers.queries.get_batch_no", + filters: filters } } }); @@ -628,7 +620,7 @@ erpnext.selling.SellingController = erpnext.TransactionController.extend({ // Help for Sales BOM items var set_sales_bom_help = function(doc) { if(!cur_frm.fields_dict.packing_list) return; - if (getchildren('Delivery Note Packing Item', doc.name, 'packing_details').length) { + if (getchildren('Packed Item', doc.name, 'packing_details').length) { $(cur_frm.fields_dict.packing_list.row.wrapper).toggle(true); if (inList(['Delivery Note', 'Sales Invoice'], doc.doctype)) { diff --git a/stock/doctype/delivery_note/delivery_note.js b/stock/doctype/delivery_note/delivery_note.js index 29b3e47b32e..0ca1d34ed25 100644 --- a/stock/doctype/delivery_note/delivery_note.js +++ b/stock/doctype/delivery_note/delivery_note.js @@ -9,7 +9,7 @@ cur_frm.cscript.sales_team_fname = "sales_team"; wn.require('app/accounts/doctype/sales_taxes_and_charges_master/sales_taxes_and_charges_master.js'); wn.require('app/utilities/doctype/sms_control/sms_control.js'); -wn.require('app/selling/doctype/sales_common/sales_common.js'); +wn.require('app/selling/sales_common.js'); wn.require('app/accounts/doctype/sales_invoice/pos.js'); wn.provide("erpnext.stock"); @@ -113,13 +113,6 @@ cur_frm.fields_dict['project_name'].get_query = function(doc, cdt, cdn) { } } -cur_frm.cscript.serial_no = function(doc, cdt, cdn) { - var d = locals[cdt][cdn]; - if (d.serial_no) { - return get_server_fields('get_serial_details',d.serial_no,'delivery_note_details',doc,cdt,cdn,1); - } -} - cur_frm.fields_dict['transporter_name'].get_query = function(doc) { return{ filters: { 'supplier_type': "transporter" } diff --git a/stock/doctype/delivery_note/delivery_note.py b/stock/doctype/delivery_note/delivery_note.py index 897c7d4d32a..8d325f4bb38 100644 --- a/stock/doctype/delivery_note/delivery_note.py +++ b/stock/doctype/delivery_note/delivery_note.py @@ -4,7 +4,7 @@ from __future__ import unicode_literals import webnotes -from webnotes.utils import cstr, flt, cint, add_days +from webnotes.utils import cstr, flt, cint from webnotes.model.bean import getlist from webnotes.model.code import get_obj from webnotes import msgprint, _ @@ -42,14 +42,6 @@ class DocType(SellingController): def get_portal_page(self): return "shipment" if self.doc.docstatus==1 else None - - def get_contact_details(self): - return get_obj('Sales Common').get_contact_details(self,0) - - - def get_comm_rate(self, sales_partner): - """Get Commission rate of Sales Partner""" - return get_obj('Sales Common').get_comm_rate(sales_partner, self) def set_actual_qty(self): for d in getlist(self.doclist, 'delivery_note_details'): @@ -57,15 +49,6 @@ class DocType(SellingController): actual_qty = webnotes.conn.sql("select actual_qty from `tabBin` where item_code = '%s' and warehouse = '%s'" % (d.item_code, d.warehouse)) d.actual_qty = actual_qty and flt(actual_qty[0][0]) or 0 - - def get_barcode_details(self, barcode): - return get_obj('Sales Common').get_barcode_details(barcode) - - - def get_adj_percent(self, arg=''): - """Re-calculates Basic Rate & amount based on Price List Selected""" - get_obj('Sales Common').get_adj_percent(self) - def so_required(self): """check in manage account if sales order required or not""" if webnotes.conn.get_value("Selling Settings", None, 'so_required') == 'Yes': @@ -83,15 +66,10 @@ class DocType(SellingController): self.so_required() self.validate_proj_cust() - sales_com_obj = get_obj(dt = 'Sales Common') - sales_com_obj.check_stop_sales_order(self) - sales_com_obj.check_active_sales_items(self) + self.check_stop_sales_order("against_sales_order") self.validate_for_items() self.validate_warehouse() - self.validate_uom_is_integer("stock_uom", "qty") - - sales_com_obj.validate_max_discount(self, 'delivery_note_details') - + self.validate_uom_is_integer("stock_uom", "qty") # Set actual qty for each item in selected warehouse self.update_current_stock() @@ -169,7 +147,8 @@ class DocType(SellingController): d.projected_qty = bin and flt(bin[0]['projected_qty']) or 0 def on_update(self): - self.doclist = get_obj('Sales Common').make_packing_list(self,'delivery_note_details') + from stock.doctype.packed_item.packed_item import make_packing_list + self.doclist = make_packing_list(self, 'delivery_note_details') def on_submit(self): self.validate_packed_qty() @@ -192,8 +171,7 @@ class DocType(SellingController): def on_cancel(self): - sales_com_obj = get_obj(dt = 'Sales Common') - sales_com_obj.check_stop_sales_order(self) + self.check_stop_sales_order("against_sales_order") self.check_next_docstatus() self.update_prevdoc_status() @@ -282,9 +260,6 @@ class DocType(SellingController): } update_bin(args) - def get_item_list(self): - return get_obj('Sales Common').get_item_list(self) - def credit_limit(self): """check credit limit of items in DN Detail which are not fetched from sales order""" amount, total = 0, 0 @@ -293,7 +268,7 @@ class DocType(SellingController): amount += d.amount if amount != 0: total = (amount/self.doc.net_total)*self.doc.grand_total - get_obj('Sales Common').check_credit(self, total) + self.check_credit(total) def get_invoiced_qty_map(delivery_note): """returns a map: {dn_detail: invoiced_qty}""" diff --git a/stock/doctype/delivery_note/delivery_note.txt b/stock/doctype/delivery_note/delivery_note.txt index 6834365b3f3..037b4fb83e5 100644 --- a/stock/doctype/delivery_note/delivery_note.txt +++ b/stock/doctype/delivery_note/delivery_note.txt @@ -355,7 +355,7 @@ "label": "Packing Details", "oldfieldname": "packing_details", "oldfieldtype": "Table", - "options": "Delivery Note Packing Item", + "options": "Packed Item", "print_hide": 1, "read_only": 1 }, diff --git a/stock/doctype/delivery_note_packing_item/README.md b/stock/doctype/delivery_note_packing_item/README.md deleted file mode 100644 index 20c343a0c76..00000000000 --- a/stock/doctype/delivery_note_packing_item/README.md +++ /dev/null @@ -1 +0,0 @@ -Item packed in parent Delivery Note. If shipped Items are of type Sales BOM, then this table contains the exploded list of Items shipped. \ No newline at end of file diff --git a/stock/doctype/delivery_note_packing_item/__init__.py b/stock/doctype/delivery_note_packing_item/__init__.py deleted file mode 100644 index baffc488252..00000000000 --- a/stock/doctype/delivery_note_packing_item/__init__.py +++ /dev/null @@ -1 +0,0 @@ -from __future__ import unicode_literals diff --git a/stock/doctype/delivery_note_packing_item/delivery_note_packing_item.py b/stock/doctype/delivery_note_packing_item/delivery_note_packing_item.py deleted file mode 100644 index 26d0f769688..00000000000 --- a/stock/doctype/delivery_note_packing_item/delivery_note_packing_item.py +++ /dev/null @@ -1,9 +0,0 @@ -# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. -# License: GNU General Public License v3. See license.txt - -from __future__ import unicode_literals -import webnotes - -class DocType: - def __init__(self, d, dl): - self.doc, self.doclist = d, dl \ No newline at end of file diff --git a/stock/doctype/delivery_note_packing_item/delivery_note_packing_item.txt b/stock/doctype/delivery_note_packing_item/delivery_note_packing_item.txt deleted file mode 100644 index 441b13a1a9f..00000000000 --- a/stock/doctype/delivery_note_packing_item/delivery_note_packing_item.txt +++ /dev/null @@ -1,170 +0,0 @@ -[ - { - "creation": "2013-02-22 01:28:00", - "docstatus": 0, - "modified": "2013-07-10 14:54:08", - "modified_by": "Administrator", - "owner": "Administrator" - }, - { - "doctype": "DocType", - "istable": 1, - "module": "Stock", - "name": "__common__" - }, - { - "doctype": "DocField", - "name": "__common__", - "parent": "Delivery Note Packing Item", - "parentfield": "fields", - "parenttype": "DocType", - "permlevel": 0 - }, - { - "doctype": "DocType", - "name": "Delivery Note Packing Item" - }, - { - "doctype": "DocField", - "fieldname": "parent_item", - "fieldtype": "Link", - "in_list_view": 1, - "label": "Parent Item", - "oldfieldname": "parent_item", - "oldfieldtype": "Link", - "options": "Item", - "read_only": 1 - }, - { - "doctype": "DocField", - "fieldname": "item_code", - "fieldtype": "Link", - "in_filter": 1, - "in_list_view": 1, - "label": "Item Code", - "oldfieldname": "item_code", - "oldfieldtype": "Link", - "options": "Item", - "read_only": 1 - }, - { - "doctype": "DocField", - "fieldname": "item_name", - "fieldtype": "Data", - "in_filter": 1, - "in_list_view": 1, - "label": "Item Name", - "oldfieldname": "item_name", - "oldfieldtype": "Data", - "read_only": 1 - }, - { - "doctype": "DocField", - "fieldname": "parent_detail_docname", - "fieldtype": "Data", - "hidden": 1, - "in_list_view": 0, - "label": "Parent Detail docname", - "no_copy": 1, - "oldfieldname": "parent_detail_docname", - "oldfieldtype": "Data", - "print_hide": 1, - "read_only": 1 - }, - { - "doctype": "DocField", - "fieldname": "description", - "fieldtype": "Text", - "in_list_view": 1, - "label": "Description", - "oldfieldname": "description", - "oldfieldtype": "Text", - "print_width": "300px", - "read_only": 1, - "width": "300px" - }, - { - "doctype": "DocField", - "fieldname": "warehouse", - "fieldtype": "Link", - "in_list_view": 1, - "label": "Warehouse", - "oldfieldname": "warehouse", - "oldfieldtype": "Link", - "options": "Warehouse" - }, - { - "doctype": "DocField", - "fieldname": "qty", - "fieldtype": "Float", - "in_list_view": 1, - "label": "Qty", - "oldfieldname": "qty", - "oldfieldtype": "Currency", - "read_only": 1 - }, - { - "doctype": "DocField", - "fieldname": "serial_no", - "fieldtype": "Text", - "label": "Serial No" - }, - { - "doctype": "DocField", - "fieldname": "batch_no", - "fieldtype": "Data", - "label": "Batch No" - }, - { - "doctype": "DocField", - "fieldname": "actual_qty", - "fieldtype": "Float", - "label": "Actual Qty", - "no_copy": 1, - "oldfieldname": "actual_qty", - "oldfieldtype": "Currency", - "read_only": 1 - }, - { - "doctype": "DocField", - "fieldname": "projected_qty", - "fieldtype": "Float", - "label": "Projected Qty", - "no_copy": 1, - "oldfieldname": "projected_qty", - "oldfieldtype": "Currency", - "read_only": 1 - }, - { - "doctype": "DocField", - "fieldname": "uom", - "fieldtype": "Link", - "label": "UOM", - "oldfieldname": "uom", - "oldfieldtype": "Link", - "options": "UOM", - "read_only": 1, - "search_index": 0 - }, - { - "doctype": "DocField", - "fieldname": "prevdoc_doctype", - "fieldtype": "Data", - "hidden": 1, - "label": "Prevdoc DocType", - "oldfieldname": "prevdoc_doctype", - "oldfieldtype": "Data", - "print_hide": 1, - "read_only": 1 - }, - { - "allow_on_submit": 1, - "doctype": "DocField", - "fieldname": "page_break", - "fieldtype": "Check", - "label": "Page Break", - "oldfieldname": "page_break", - "oldfieldtype": "Check", - "read_only": 1 - } -] \ No newline at end of file diff --git a/translations/ar.csv b/translations/ar.csv index 9e075a8c1a6..98565806bfa 100644 --- a/translations/ar.csv +++ b/translations/ar.csv @@ -814,7 +814,7 @@ Delivery Note Item,ملاحظة تسليم السلعة Delivery Note Items,ملاحظة عناصر التسليم Delivery Note Message,ملاحظة تسليم رسالة Delivery Note No,ملاحظة لا تسليم -Delivery Note Packing Item,ملاحظة التوصيل التغليف +Packed Item,ملاحظة التوصيل التغليف Delivery Note Required,ملاحظة التسليم المطلوبة Delivery Note Trends,ملاحظة اتجاهات التسليم Delivery Status,حالة التسليم diff --git a/translations/de.csv b/translations/de.csv index ccb2c88fc2f..7cf514e3ec9 100644 --- a/translations/de.csv +++ b/translations/de.csv @@ -814,7 +814,7 @@ Delivery Note Item,Lieferscheinposition Delivery Note Items,Lieferscheinpositionen Delivery Note Message,Lieferschein Nachricht Delivery Note No,Lieferschein Nein -Delivery Note Packing Item,Lieferschein Verpackung Artikel +Packed Item,Lieferschein Verpackung Artikel Delivery Note Required,Lieferschein erforderlich Delivery Note Trends,Lieferschein Trends Delivery Status,Lieferstatus diff --git a/translations/el.csv b/translations/el.csv index 7d429bb4e17..8b604e7c4b7 100644 --- a/translations/el.csv +++ b/translations/el.csv @@ -827,7 +827,7 @@ Delivery Note Item,Αποστολή στοιχείων Σημείωση Delivery Note Items,Σημείωση Στοιχεία Παράδοσης Delivery Note Message,Αποστολή μηνύματος Σημείωση Delivery Note No,Σημείωση παράδοσης αριθ. -Delivery Note Packing Item,Παράδοση Θέση Συσκευασία Σημείωση +Packed Item,Παράδοση Θέση Συσκευασία Σημείωση Delivery Note Required,Σημείωση παράδοσης Απαιτείται Delivery Note Trends,Τάσεις Σημείωση Παράδοση Delivery Status,Κατάσταση παράδοσης diff --git a/translations/es.csv b/translations/es.csv index d30649d4cf7..4ab32b5eb79 100644 --- a/translations/es.csv +++ b/translations/es.csv @@ -814,7 +814,7 @@ Delivery Note Item,Nota de entrega del artículo Delivery Note Items,Artículos de entrega Nota Delivery Note Message,Entrega de mensajes Nota Delivery Note No,Entrega Nota No -Delivery Note Packing Item,Nota de Entrega Embalaje artículo +Packed Item,Nota de Entrega Embalaje artículo Delivery Note Required,Nota de entrega requerida Delivery Note Trends,Tendencias albarán Delivery Status,Estado de entrega diff --git a/translations/fr.csv b/translations/fr.csv index dacdd2f27f5..d9c0d8718e9 100644 --- a/translations/fr.csv +++ b/translations/fr.csv @@ -814,7 +814,7 @@ Delivery Note Item,Point de Livraison Delivery Note Items,Articles bordereau de livraison Delivery Note Message,Note Message de livraison Delivery Note No,Remarque Aucune livraison -Delivery Note Packing Item,Article d'emballage de livraison Note +Packed Item,Article d'emballage de livraison Note Delivery Note Required,Remarque livraison requis Delivery Note Trends,Bordereau de livraison Tendances Delivery Status,Delivery Status diff --git a/translations/hi.csv b/translations/hi.csv index 6f9576c5b4c..8e2fcaf5ed0 100644 --- a/translations/hi.csv +++ b/translations/hi.csv @@ -814,7 +814,7 @@ Delivery Note Item,डिलिवरी नोट आइटम Delivery Note Items,डिलिवरी नोट आइटम Delivery Note Message,डिलिवरी नोट संदेश Delivery Note No,डिलिवरी नोट -Delivery Note Packing Item,डिलिवरी नोट पैकिंग आइटम +Packed Item,डिलिवरी नोट पैकिंग आइटम Delivery Note Required,डिलिवरी नोट आवश्यक Delivery Note Trends,डिलिवरी नोट रुझान Delivery Status,डिलिवरी स्थिति diff --git a/translations/hr.csv b/translations/hr.csv index d60f85b96c7..20b5cc7421b 100644 --- a/translations/hr.csv +++ b/translations/hr.csv @@ -814,7 +814,7 @@ Delivery Note Item,Otpremnica artikla Delivery Note Items,Način Napomena Stavke Delivery Note Message,Otpremnica Poruka Delivery Note No,Dostava Napomena Ne -Delivery Note Packing Item,Dostava Napomena Pakiranje artikla +Packed Item,Dostava Napomena Pakiranje artikla Delivery Note Required,Dostava Napomena Obavezno Delivery Note Trends,Otpremnici trendovi Delivery Status,Status isporuke diff --git a/translations/it.csv b/translations/it.csv index c91fc84759f..e9e21064f93 100644 --- a/translations/it.csv +++ b/translations/it.csv @@ -822,7 +822,7 @@ Delivery Note Item,Nota articolo Consegna Delivery Note Items,Nota Articoli Consegna Delivery Note Message,Nota Messaggio Consegna Delivery Note No,Nota Consegna N. -Delivery Note Packing Item,Nota Consegna Imballaggio articolo +Packed Item,Nota Consegna Imballaggio articolo Delivery Note Required,Nota Consegna Richiesta Delivery Note Trends,Nota Consegna Tendenza Delivery Status,Stato Consegna diff --git a/translations/nl.csv b/translations/nl.csv index 3cc71524f6c..c9b5aa214a4 100644 --- a/translations/nl.csv +++ b/translations/nl.csv @@ -814,7 +814,7 @@ Delivery Note Item,Levering Note Item Delivery Note Items,Levering Opmerking Items Delivery Note Message,Levering Opmerking Bericht Delivery Note No,Levering aantekening -Delivery Note Packing Item,Levering Opmerking Verpakking Item +Packed Item,Levering Opmerking Verpakking Item Delivery Note Required,Levering Opmerking Verplicht Delivery Note Trends,Delivery Note Trends Delivery Status,Delivery Status diff --git a/translations/pt-BR.csv b/translations/pt-BR.csv index 274c7d4947b..7dfb0a2af85 100644 --- a/translations/pt-BR.csv +++ b/translations/pt-BR.csv @@ -814,7 +814,7 @@ Delivery Note Item,Item da Guia de Remessa Delivery Note Items,Itens da Guia de Remessa Delivery Note Message,Mensagem da Guia de Remessa Delivery Note No,Nº da Guia de Remessa -Delivery Note Packing Item,Item do Pacote da Guia de Remessa +Packed Item,Item do Pacote da Guia de Remessa Delivery Note Required,Guia de Remessa Obrigatória Delivery Note Trends,Nota de entrega Trends Delivery Status,Estado da entrega diff --git a/translations/pt.csv b/translations/pt.csv index 31d20bcd460..900d4daa179 100644 --- a/translations/pt.csv +++ b/translations/pt.csv @@ -814,7 +814,7 @@ Delivery Note Item,Item Nota de Entrega Delivery Note Items,Nota Itens de entrega Delivery Note Message,Mensagem Nota de Entrega Delivery Note No,Nota de Entrega Não -Delivery Note Packing Item,Entrega do item embalagem Nota +Packed Item,Entrega do item embalagem Nota Delivery Note Required,Nota de Entrega Obrigatório Delivery Note Trends,Nota de entrega Trends Delivery Status,Estado entrega diff --git a/translations/sr.csv b/translations/sr.csv index aa14049f254..fc9513b4c24 100644 --- a/translations/sr.csv +++ b/translations/sr.csv @@ -814,7 +814,7 @@ Delivery Note Item,Испорука Напомена Ставка Delivery Note Items,Достава Напомена Ставке Delivery Note Message,Испорука Напомена порука Delivery Note No,Испорука Напомена Не -Delivery Note Packing Item,Испорука Напомена Паковање јединице +Packed Item,Испорука Напомена Паковање јединице Delivery Note Required,Испорука Напомена Обавезно Delivery Note Trends,Достава Напомена трендови Delivery Status,Статус испоруке diff --git a/translations/ta.csv b/translations/ta.csv index 74cc74b6952..f21f27b8259 100644 --- a/translations/ta.csv +++ b/translations/ta.csv @@ -814,7 +814,7 @@ Delivery Note Item,டெலிவரி குறிப்பு பொர Delivery Note Items,டெலிவரி குறிப்பு உருப்படிகள் Delivery Note Message,டெலிவரி குறிப்பு செய்தி Delivery Note No,டெலிவரி குறிப்பு இல்லை -Delivery Note Packing Item,டெலிவரி குறிப்பு தடைக்காப்பு பொருள் +Packed Item,டெலிவரி குறிப்பு தடைக்காப்பு பொருள் Delivery Note Required,டெலிவரி குறிப்பு தேவை Delivery Note Trends,பந்து குறிப்பு போக்குகள் Delivery Status,விநியோக நிலைமை diff --git a/translations/th.csv b/translations/th.csv index 7a461f070fa..3cf2d9c210c 100644 --- a/translations/th.csv +++ b/translations/th.csv @@ -814,7 +814,7 @@ Delivery Note Item,รายการจัดส่งสินค้าหม Delivery Note Items,รายการจัดส่งสินค้าหมายเหตุ Delivery Note Message,ข้อความหมายเหตุจัดส่งสินค้า Delivery Note No,หมายเหตุจัดส่งสินค้าไม่มี -Delivery Note Packing Item,จัดส่งสินค้าบรรจุหมายเหตุ +Packed Item,จัดส่งสินค้าบรรจุหมายเหตุ Delivery Note Required,หมายเหตุจัดส่งสินค้าที่จำเป็น Delivery Note Trends,แนวโน้มหมายเหตุการจัดส่งสินค้า Delivery Status,สถานะการจัดส่งสินค้า diff --git a/utilities/repost_stock.py b/utilities/repost_stock.py index 735930486e8..9591b31e80c 100644 --- a/utilities/repost_stock.py +++ b/utilities/repost_stock.py @@ -53,7 +53,7 @@ def get_reserved_qty(item_code, warehouse): from ( select qty, parent_detail_docname, parent, name - from `tabDelivery Note Packing Item` dnpi_in + from `tabPacked Item` dnpi_in where item_code = %s and warehouse = %s and parenttype="Sales Order" and item_code != parent_item From ef00af32c104e602b34a9370d6af0d6c372baee3 Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Fri, 18 Oct 2013 13:02:57 +0530 Subject: [PATCH 187/200] [minor] deleted sales common py --- selling/doctype/sales_common/sales_common.py | 348 ------------------- 1 file changed, 348 deletions(-) delete mode 100644 selling/doctype/sales_common/sales_common.py diff --git a/selling/doctype/sales_common/sales_common.py b/selling/doctype/sales_common/sales_common.py deleted file mode 100644 index ad626da4600..00000000000 --- a/selling/doctype/sales_common/sales_common.py +++ /dev/null @@ -1,348 +0,0 @@ -# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. -# License: GNU General Public License v3. See license.txt - -from __future__ import unicode_literals -import webnotes - -from webnotes.utils import cint, cstr, flt -from webnotes.model.doc import addchild -from webnotes.model.bean import getlist -from webnotes.model.code import get_obj -from webnotes import msgprint, _ -from setup.utils import get_company_currency - -get_value = webnotes.conn.get_value - -from utilities.transaction_base import TransactionBase - -class DocType(TransactionBase): - def __init__(self,d,dl): - self.doc, self.doclist = d, dl - - - def get_contact_details(self, obj = '', primary = 0): - cond = " and contact_name = '"+cstr(obj.doc.contact_person)+"'" - if primary: cond = " and is_primary_contact = 'Yes'" - contact = webnotes.conn.sql("select contact_name, contact_no, email_id, contact_address from `tabContact` where customer = '%s' and docstatus != 2 %s" %(obj.doc.customer, cond), as_dict = 1) - if not contact: - return - c = contact[0] - obj.doc.contact_person = c['contact_name'] or '' - obj.doc.contact_no = c['contact_no'] or '' - obj.doc.email_id = c['email_id'] or '' - obj.doc.customer_mobile_no = c['contact_no'] or '' - if c['contact_address']: - obj.doc.customer_address = c['contact_address'] - - def get_invoice_details(self, obj = ''): - if obj.doc.company: - acc_head = webnotes.conn.sql("select name from `tabAccount` where name = '%s' and docstatus != 2" % (cstr(obj.doc.customer) + " - " + webnotes.conn.get_value('Company', obj.doc.company, 'abbr'))) - obj.doc.debit_to = acc_head and acc_head[0][0] or '' - - def get_tax_details(self, item_code, obj): - import json - tax = webnotes.conn.sql("select tax_type, tax_rate from `tabItem Tax` where parent = %s" , item_code) - t = {} - for x in tax: t[x[0]] = flt(x[1]) - ret = { - 'item_tax_rate' : tax and json.dumps(t) or '' - } - return ret - - def get_serial_details(self, serial_no, obj): - import json - item = webnotes.conn.sql("select item_code, make, label,brand, description from `tabSerial No` where name = '%s' and docstatus != 2" %(serial_no), as_dict=1) - tax = webnotes.conn.sql("select tax_type, tax_rate from `tabItem Tax` where parent = %s" , item[0]['item_code']) - t = {} - for x in tax: t[x[0]] = flt(x[1]) - ret = { - 'item_code' : item and item[0]['item_code'] or '', - 'make' : item and item[0]['make'] or '', - 'label' : item and item[0]['label'] or '', - 'brand' : item and item[0]['brand'] or '', - 'description' : item and item[0]['description'] or '', - 'item_tax_rate' : json.dumps(t) - } - return ret - - # To verify whether rate entered in details table does not exceed max discount % - # ======================================================================================= - def validate_max_discount(self,obj, detail_table): - for d in getlist(obj.doclist, detail_table): - discount = webnotes.conn.sql("select max_discount from tabItem where name = '%s'" %(d.item_code),as_dict = 1) - if discount and discount[0]['max_discount'] and (flt(d.adj_rate)>flt(discount[0]['max_discount'])): - msgprint("You cannot give more than " + cstr(discount[0]['max_discount']) + " % discount on Item Code : "+cstr(d.item_code)) - raise Exception - - # Get Tax rate if account type is TAX - # ========================================================================= - def get_rate(self, arg): - arg = eval(arg) - rate = webnotes.conn.sql("select account_type, tax_rate from `tabAccount` where name = '%s' and docstatus != 2" %(arg['account_head']), as_dict=1) - ret = {'rate' : 0} - if arg['charge_type'] == 'Actual' and rate[0]['account_type'] == 'Tax': - msgprint("You cannot select ACCOUNT HEAD of type TAX as your CHARGE TYPE is 'ACTUAL'") - ret = { - 'account_head' : '' - } - elif rate[0]['account_type'] in ['Tax', 'Chargeable'] and not arg['charge_type'] == 'Actual': - ret = { - 'rate' : rate and flt(rate[0]['tax_rate']) or 0 - } - return ret - - - def get_item_list(self, obj, is_stopped=0): - """get item list""" - il = [] - for d in getlist(obj.doclist, obj.fname): - reserved_warehouse = "" - reserved_qty_for_main_item = 0 - - if obj.doc.doctype == "Sales Order": - if (webnotes.conn.get_value("Item", d.item_code, "is_stock_item") == 'Yes' or - self.has_sales_bom(d.item_code)) and not d.reserved_warehouse: - webnotes.throw(_("Please enter Reserved Warehouse for item ") + - d.item_code + _(" as it is stock Item or packing item")) - reserved_warehouse = d.reserved_warehouse - if flt(d.qty) > flt(d.delivered_qty): - reserved_qty_for_main_item = flt(d.qty) - flt(d.delivered_qty) - - if obj.doc.doctype == "Delivery Note" and d.prevdoc_doctype == 'Sales Order': - # if SO qty is 10 and there is tolerance of 20%, then it will allow DN of 12. - # But in this case reserved qty should only be reduced by 10 and not 12 - - already_delivered_qty = self.get_already_delivered_qty(obj.doc.name, - d.prevdoc_docname, d.prevdoc_detail_docname) - so_qty, reserved_warehouse = self.get_so_qty_and_warehouse(d.prevdoc_detail_docname) - - if already_delivered_qty + d.qty > so_qty: - reserved_qty_for_main_item = -(so_qty - already_delivered_qty) - else: - reserved_qty_for_main_item = -flt(d.qty) - - if self.has_sales_bom(d.item_code): - for p in getlist(obj.doclist, 'packing_details'): - if p.parent_detail_docname == d.name and p.parent_item == d.item_code: - # the packing details table's qty is already multiplied with parent's qty - il.append(webnotes._dict({ - 'warehouse': p.warehouse, - 'reserved_warehouse': reserved_warehouse, - 'item_code': p.item_code, - 'qty': flt(p.qty), - 'reserved_qty': (flt(p.qty)/flt(d.qty)) * reserved_qty_for_main_item, - 'uom': p.uom, - 'batch_no': cstr(p.batch_no).strip(), - 'serial_no': cstr(p.serial_no).strip(), - 'name': d.name - })) - else: - il.append(webnotes._dict({ - 'warehouse': d.warehouse, - 'reserved_warehouse': reserved_warehouse, - 'item_code': d.item_code, - 'qty': d.qty, - 'reserved_qty': reserved_qty_for_main_item, - 'uom': d.stock_uom, - 'batch_no': cstr(d.batch_no).strip(), - 'serial_no': cstr(d.serial_no).strip(), - 'name': d.name - })) - return il - - def get_already_delivered_qty(self, dn, so, so_detail): - qty = webnotes.conn.sql("""select sum(qty) from `tabDelivery Note Item` - where prevdoc_detail_docname = %s and docstatus = 1 - and prevdoc_doctype = 'Sales Order' and prevdoc_docname = %s - and parent != %s""", (so_detail, so, dn)) - return qty and flt(qty[0][0]) or 0.0 - - def get_so_qty_and_warehouse(self, so_detail): - so_item = webnotes.conn.sql("""select qty, reserved_warehouse from `tabSales Order Item` - where name = %s and docstatus = 1""", so_detail, as_dict=1) - so_qty = so_item and flt(so_item[0]["qty"]) or 0.0 - so_warehouse = so_item and so_item[0]["reserved_warehouse"] or "" - return so_qty, so_warehouse - - def has_sales_bom(self, item_code): - return webnotes.conn.sql("select name from `tabSales BOM` where new_item_code=%s and docstatus != 2", item_code) - - def get_sales_bom_items(self, item_code): - return webnotes.conn.sql("""select t1.item_code, t1.qty, t1.uom - from `tabSales BOM Item` t1, `tabSales BOM` t2 - where t2.new_item_code=%s and t1.parent = t2.name""", item_code, as_dict=1) - - def get_packing_item_details(self, item): - return webnotes.conn.sql("select item_name, description, stock_uom from `tabItem` where name = %s", item, as_dict = 1)[0] - - def get_bin_qty(self, item, warehouse): - det = webnotes.conn.sql("select actual_qty, projected_qty from `tabBin` where item_code = '%s' and warehouse = '%s'" % (item, warehouse), as_dict = 1) - return det and det[0] or '' - - def update_packing_list_item(self,obj, packing_item_code, qty, warehouse, line): - bin = self.get_bin_qty(packing_item_code, warehouse) - item = self.get_packing_item_details(packing_item_code) - - # check if exists - exists = 0 - for d in getlist(obj.doclist, 'packing_details'): - if d.parent_item == line.item_code and d.item_code == packing_item_code and d.parent_detail_docname == line.name: - pi, exists = d, 1 - break - - if not exists: - pi = addchild(obj.doc, 'packing_details', 'Delivery Note Packing Item', - obj.doclist) - - pi.parent_item = line.item_code - pi.item_code = packing_item_code - pi.item_name = item['item_name'] - pi.parent_detail_docname = line.name - pi.description = item['description'] - pi.uom = item['stock_uom'] - pi.qty = flt(qty) - pi.actual_qty = bin and flt(bin['actual_qty']) or 0 - pi.projected_qty = bin and flt(bin['projected_qty']) or 0 - pi.prevdoc_doctype = line.prevdoc_doctype - if not pi.warehouse: - pi.warehouse = warehouse - if not pi.batch_no: - pi.batch_no = cstr(line.batch_no) - pi.idx = self.packing_list_idx - - # saved, since this function is called on_update of delivery note - pi.save() - - self.packing_list_idx += 1 - - - def make_packing_list(self, obj, fname): - """make packing list for sales bom item""" - self.packing_list_idx = 0 - parent_items = [] - for d in getlist(obj.doclist, fname): - warehouse = fname == "sales_order_details" and d.reserved_warehouse or d.warehouse - if self.has_sales_bom(d.item_code): - for i in self.get_sales_bom_items(d.item_code): - self.update_packing_list_item(obj, i['item_code'], flt(i['qty'])*flt(d.qty), warehouse, d) - - if [d.item_code, d.name] not in parent_items: - parent_items.append([d.item_code, d.name]) - - obj.doclist = self.cleanup_packing_list(obj, parent_items) - - return obj.doclist - - def cleanup_packing_list(self, obj, parent_items): - """Remove all those child items which are no longer present in main item table""" - delete_list = [] - for d in getlist(obj.doclist, 'packing_details'): - if [d.parent_item, d.parent_detail_docname] not in parent_items: - # mark for deletion from doclist - delete_list.append(d.name) - - if not delete_list: - return obj.doclist - - # delete from doclist - obj.doclist = webnotes.doclist(filter(lambda d: d.name not in delete_list, obj.doclist)) - - # delete from db - webnotes.conn.sql("""\ - delete from `tabDelivery Note Packing Item` - where name in (%s)""" - % (", ".join(["%s"] * len(delete_list))), - tuple(delete_list)) - - return obj.doclist - - - def get_month(self,date): - """Get month based on date (required in sales person and sales partner)""" - month_list = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'] - month_idx = cint(cstr(date).split('-')[1])-1 - return month_list[month_idx] - - - # **** Check for Stop SO as no transactions can be made against Stopped SO. Need to unstop it. *** - def check_stop_sales_order(self,obj): - for d in getlist(obj.doclist,obj.fname): - ref_doc_name = '' - if d.fields.has_key('prevdoc_docname') and d.prevdoc_docname and d.prevdoc_doctype == 'Sales Order': - ref_doc_name = d.prevdoc_docname - elif d.fields.has_key('sales_order') and d.sales_order and not d.delivery_note: - ref_doc_name = d.sales_order - if ref_doc_name: - so_status = webnotes.conn.sql("select status from `tabSales Order` where name = %s",ref_doc_name) - so_status = so_status and so_status[0][0] or '' - if so_status == 'Stopped': - msgprint("You cannot do any transaction against Sales Order : '%s' as it is Stopped." %(ref_doc_name)) - raise Exception - - def check_active_sales_items(self,obj): - for d in getlist(obj.doclist, obj.fname): - if d.item_code: - item = webnotes.conn.sql("""select docstatus, is_sales_item, - is_service_item, default_income_account from tabItem where name = %s""", - d.item_code, as_dict=True)[0] - if item.is_sales_item == 'No' and item.is_service_item == 'No': - msgprint("Item : '%s' is neither Sales nor Service Item" % (d.item_code)) - raise Exception - if d.income_account and not item.default_income_account: - webnotes.conn.set_value("Item", d.item_code, "default_income_account", d.income_account) - - - def check_credit(self,obj,grand_total): - acc_head = webnotes.conn.sql("select name from `tabAccount` where company = '%s' and master_name = '%s'"%(obj.doc.company, obj.doc.customer)) - if acc_head: - tot_outstanding = 0 - dbcr = webnotes.conn.sql("""select sum(debit), sum(credit) from `tabGL Entry` - where account = %s""", acc_head[0][0]) - if dbcr: - tot_outstanding = flt(dbcr[0][0])-flt(dbcr[0][1]) - - exact_outstanding = flt(tot_outstanding) + flt(grand_total) - get_obj('Account',acc_head[0][0]).check_credit_limit(acc_head[0][0], obj.doc.company, exact_outstanding) - - def get_prevdoc_date(self, obj): - for d in getlist(obj.doclist, obj.fname): - if d.prevdoc_doctype and d.prevdoc_docname: - if d.prevdoc_doctype in ["Sales Invoice", "Delivery Note"]: - date_field = "posting_date" - else: - date_field = "transaction_date" - - d.prevdoc_date = webnotes.conn.get_value(d.prevdoc_doctype, - d.prevdoc_docname, date_field) - -def get_batch_no(doctype, txt, searchfield, start, page_len, filters): - from controllers.queries import get_match_cond - - if filters.has_key('warehouse'): - return webnotes.conn.sql("""select batch_no from `tabStock Ledger Entry` sle - where item_code = '%(item_code)s' - and warehouse = '%(warehouse)s' - and batch_no like '%(txt)s' - and exists(select * from `tabBatch` - where name = sle.batch_no - and (ifnull(expiry_date, '')='' or expiry_date >= '%(posting_date)s') - and docstatus != 2) - %(mcond)s - group by batch_no having sum(actual_qty) > 0 - order by batch_no desc - limit %(start)s, %(page_len)s """ % {'item_code': filters['item_code'], - 'warehouse': filters['warehouse'], 'posting_date': filters['posting_date'], - 'txt': "%%%s%%" % txt, 'mcond':get_match_cond(doctype, searchfield), - 'start': start, 'page_len': page_len}) - else: - return webnotes.conn.sql("""select name from tabBatch - where docstatus != 2 - and item = '%(item_code)s' - and (ifnull(expiry_date, '')='' or expiry_date >= '%(posting_date)s') - and name like '%(txt)s' - %(mcond)s - order by name desc - limit %(start)s, %(page_len)s""" % {'item_code': filters['item_code'], - 'posting_date': filters['posting_date'], 'txt': "%%%s%%" % txt, - 'mcond':get_match_cond(doctype, searchfield),'start': start, - 'page_len': page_len}) From 1b0664636aeaa6a3f107dd70f16ed6a697bdc24b Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Fri, 18 Oct 2013 13:07:28 +0530 Subject: [PATCH 188/200] [fix] [conflict] --- selling/doctype/quotation/quotation.py | 39 -------------------------- 1 file changed, 39 deletions(-) diff --git a/selling/doctype/quotation/quotation.py b/selling/doctype/quotation/quotation.py index dbc496b6d2d..53531278e4d 100644 --- a/selling/doctype/quotation/quotation.py +++ b/selling/doctype/quotation/quotation.py @@ -59,40 +59,10 @@ class DocType(SellingController): self.validate_for_items() self.validate_uom_is_integer("stock_uom", "qty") -<<<<<<< HEAD def update_opportunity(self): for opportunity in self.doclist.get_distinct_values("prevdoc_docname"): webnotes.bean("Opportunity", opportunity).get_controller().set_status(update=True) -======= - sales_com_obj = get_obj('Sales Common') - sales_com_obj.check_active_sales_items(self) - sales_com_obj.validate_max_discount(self,'quotation_details') - - def on_update(self): - # Set Quotation Status - webnotes.conn.set(self.doc, 'status', 'Draft') - #update enquiry - #------------------ - def update_enquiry(self, flag): - prevdoc='' - for d in getlist(self.doclist, 'quotation_details'): - if d.prevdoc_docname: - prevdoc = d.prevdoc_docname - - if prevdoc: - if flag == 'submit': #on submit - sql("update `tabOpportunity` set status = 'Quotation Sent' where name = %s", prevdoc) - elif flag == 'cancel': #on cancel - sql("update `tabOpportunity` set status = 'Open' where name = %s", prevdoc) - elif flag == 'order lost': #order lost - sql("update `tabOpportunity` set status = 'Opportunity Lost' where name=%s", prevdoc) - elif flag == 'order confirm': #order confirm - sql("update `tabOpportunity` set status='Order Confirmed' where name=%s", prevdoc) ->>>>>>> 8f72d9f679fca88be7710e31b6cfa66defcde81a - - # declare as order lost - #------------------------- def declare_order_lost(self, arg): if not self.has_sales_order(): webnotes.conn.set(self.doc, 'status', 'Lost') @@ -101,15 +71,11 @@ class DocType(SellingController): else: webnotes.throw(_("Cannot set as Lost as Sales Order is made.")) - #check if value entered in item table - #-------------------------------------- def check_item_table(self): if not getlist(self.doclist, 'quotation_details'): msgprint("Please enter item details") raise Exception - # ON SUBMIT - # ========================================================================= def on_submit(self): self.check_item_table() @@ -119,16 +85,11 @@ class DocType(SellingController): #update enquiry status self.update_opportunity() - -# ON CANCEL -# ========================================================================== def on_cancel(self): #update enquiry status self.set_status() self.update_opportunity() -# Print other charges -# =========================================================================== def print_other_charges(self,docname): print_lst = [] for d in getlist(self.doclist,'other_charges'): From 0bc5ae55d88883e68b75d2f7703249bacdb73aa6 Mon Sep 17 00:00:00 2001 From: Anand Doshi Date: Fri, 18 Oct 2013 16:07:47 +0530 Subject: [PATCH 189/200] [minor] fixes in data import, serial no and setup wizard --- setup/page/setup_wizard/setup_wizard.js | 7 +++++-- stock/doctype/serial_no/serial_no.py | 3 +++ 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/setup/page/setup_wizard/setup_wizard.js b/setup/page/setup_wizard/setup_wizard.js index 648958e6267..bec2828b1e5 100644 --- a/setup/page/setup_wizard/setup_wizard.js +++ b/setup/page/setup_wizard/setup_wizard.js @@ -69,7 +69,10 @@ wn.pages['setup-wizard'].onload = function(wrapper) { onload: function(slide) { if(user!=="Administrator") { slide.form.fields_dict.password.$wrapper.toggle(false); - slide.form.fields_dict.email_id.$wrapper.toggle(false); + slide.form.fields_dict.email.$wrapper.toggle(false); + slide.form.fields_dict.first_name.set_input(wn.boot.profile.first_name); + slide.form.fields_dict.last_name.set_input(wn.boot.profile.last_name); + delete slide.form.fields_dict.email; delete slide.form.fields_dict.password; } @@ -97,7 +100,7 @@ wn.pages['setup-wizard'].onload = function(wrapper) { var parts = slide.get_input("company_name").val().split(" "); var abbr = $.map(parts, function(p) { return p ? p.substr(0,1) : null }).join(""); slide.get_input("company_abbr").val(abbr.toUpperCase()); - }); + }).val(wn.boot.control_panel.company_name || "").trigger("change"); } }, diff --git a/stock/doctype/serial_no/serial_no.py b/stock/doctype/serial_no/serial_no.py index 22a16b56482..9496d6abee9 100644 --- a/stock/doctype/serial_no/serial_no.py +++ b/stock/doctype/serial_no/serial_no.py @@ -189,6 +189,9 @@ class DocType(StockController): self.set_status() self.set_purchase_details() self.set_sales_details() + + def on_communication(self): + return def process_serial_no(sle): item_det = get_item_details(sle.item_code) From 5566bcaa0e56e66a8b574243ece1a065e0534840 Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Fri, 18 Oct 2013 17:00:53 +0530 Subject: [PATCH 190/200] [cleanup] purchase common --- .../purchase_invoice/purchase_invoice.py | 10 ++-------- .../doctype/sales_invoice/sales_invoice.txt | 4 ++-- accounts/report/gross_profit/gross_profit.py | 2 +- .../purchase_common/purchase_common.py | 19 ------------------- .../doctype/purchase_order/purchase_order.py | 1 - .../supplier_quotation/supplier_quotation.py | 3 --- controllers/buying_controller.py | 9 +++++++-- .../production_order/production_order.py | 2 +- .../p06_rename_packing_list_doctype.py | 3 ++- .../material_request/material_request.py | 3 --- .../purchase_receipt/purchase_receipt.py | 1 - 11 files changed, 15 insertions(+), 42 deletions(-) diff --git a/accounts/doctype/purchase_invoice/purchase_invoice.py b/accounts/doctype/purchase_invoice/purchase_invoice.py index 8bd7e9df032..ba6f5a4d450 100644 --- a/accounts/doctype/purchase_invoice/purchase_invoice.py +++ b/accounts/doctype/purchase_invoice/purchase_invoice.py @@ -293,20 +293,14 @@ class DocType(BuyingController): reconcile_against_document(lst) def on_submit(self): - purchase_controller = webnotes.get_obj("Purchase Common") - purchase_controller.is_item_table_empty(self) - self.check_prev_docstatus() - # Check for Approving Authority - get_obj('Authorization Control').validate_approving_authority(self.doc.doctype,self.doc.company, self.doc.grand_total) - + get_obj('Authorization Control').validate_approving_authority(self.doc.doctype, + self.doc.company, self.doc.grand_total) # this sequence because outstanding may get -negative self.make_gl_entries() - self.update_against_document_in_jv() - self.update_prevdoc_status() def make_gl_entries(self): diff --git a/accounts/doctype/sales_invoice/sales_invoice.txt b/accounts/doctype/sales_invoice/sales_invoice.txt index 331a503b28d..34191885ead 100644 --- a/accounts/doctype/sales_invoice/sales_invoice.txt +++ b/accounts/doctype/sales_invoice/sales_invoice.txt @@ -2,7 +2,7 @@ { "creation": "2013-05-24 19:29:05", "docstatus": 0, - "modified": "2013-10-11 13:12:38", + "modified": "2013-10-18 13:12:38", "modified_by": "Administrator", "owner": "Administrator" }, @@ -323,7 +323,7 @@ "fieldname": "packing_details", "fieldtype": "Table", "label": "Packing Details", - "options": "Delivery Note Packing Item", + "options": "Packed Item", "print_hide": 1, "read_only": 0 }, diff --git a/accounts/report/gross_profit/gross_profit.py b/accounts/report/gross_profit/gross_profit.py index 9917b69697f..6d01af4cdf1 100644 --- a/accounts/report/gross_profit/gross_profit.py +++ b/accounts/report/gross_profit/gross_profit.py @@ -75,7 +75,7 @@ def get_item_sales_bom(): for d in webnotes.conn.sql("""select parenttype, parent, parent_item, item_code, warehouse, -1*qty as total_qty, parent_detail_docname - from `tabDelivery Note Packing Item` where docstatus=1""", as_dict=True): + from `tabPacked Item` where docstatus=1""", as_dict=True): item_sales_bom.setdefault(d.parenttype, webnotes._dict()).setdefault(d.parent, webnotes._dict()).setdefault(d.parent_item, []).append(d) diff --git a/buying/doctype/purchase_common/purchase_common.py b/buying/doctype/purchase_common/purchase_common.py index 8637e5fb43a..4d2bc00e0d8 100644 --- a/buying/doctype/purchase_common/purchase_common.py +++ b/buying/doctype/purchase_common/purchase_common.py @@ -16,25 +16,6 @@ class DocType(BuyingController): def __init__(self, doc, doclist=None): self.doc = doc self.doclist = doclist - - def is_item_table_empty(self, obj): - if not len(obj.doclist.get({"parentfield": obj.fname})): - msgprint(_("You need to put at least one item in the item table."), raise_exception=True) - - def get_supplier_details(self, name = ''): - details = webnotes.conn.sql("select supplier_name,address from `tabSupplier` where name = '%s' and docstatus != 2" %(name), as_dict = 1) - if details: - ret = { - 'supplier_name' : details and details[0]['supplier_name'] or '', - 'supplier_address' : details and details[0]['address'] or '' - } - # ********** get primary contact details (this is done separately coz. , in case there is no primary contact thn it would not be able to fetch customer details in case of join query) - contact_det = webnotes.conn.sql("select contact_name, contact_no, email_id from `tabContact` where supplier = '%s' and is_supplier = 1 and is_primary_contact = 'Yes' and docstatus != 2" %(name), as_dict = 1) - ret['contact_person'] = contact_det and contact_det[0]['contact_name'] or '' - return ret - else: - msgprint("Supplier : %s does not exists" % (name)) - raise Exception def update_last_purchase_rate(self, obj, is_submit): """updates last_purchase_rate in item table for each item""" diff --git a/buying/doctype/purchase_order/purchase_order.py b/buying/doctype/purchase_order/purchase_order.py index cf207bb7477..d3555fc25a4 100644 --- a/buying/doctype/purchase_order/purchase_order.py +++ b/buying/doctype/purchase_order/purchase_order.py @@ -147,7 +147,6 @@ class DocType(BuyingController): def on_submit(self): purchase_controller = webnotes.get_obj("Purchase Common") - purchase_controller.is_item_table_empty(self) self.update_prevdoc_status() self.update_bin(is_submit = 1, is_stopped = 0) diff --git a/buying/doctype/supplier_quotation/supplier_quotation.py b/buying/doctype/supplier_quotation/supplier_quotation.py index 8c5224e30ac..67c8360905f 100644 --- a/buying/doctype/supplier_quotation/supplier_quotation.py +++ b/buying/doctype/supplier_quotation/supplier_quotation.py @@ -26,9 +26,6 @@ class DocType(BuyingController): self.validate_uom_is_integer("uom", "qty") def on_submit(self): - purchase_controller = webnotes.get_obj("Purchase Common") - purchase_controller.is_item_table_empty(self) - webnotes.conn.set(self.doc, "status", "Submitted") def on_cancel(self): diff --git a/controllers/buying_controller.py b/controllers/buying_controller.py index c42eda50bc9..2677252da31 100644 --- a/controllers/buying_controller.py +++ b/controllers/buying_controller.py @@ -2,7 +2,7 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals -import webnotes, json +import webnotes from webnotes import _, msgprint from webnotes.utils import flt, _round @@ -12,7 +12,6 @@ from setup.utils import get_company_currency from controllers.stock_controller import StockController class BuyingController(StockController): - def onload_post_render(self): # contact, address, item details self.set_missing_values() @@ -22,6 +21,7 @@ class BuyingController(StockController): if self.doc.supplier and not self.doc.supplier_name: self.doc.supplier_name = webnotes.conn.get_value("Supplier", self.doc.supplier, "supplier_name") + self.is_item_table_empty() self.validate_stock_or_nonstock_items() self.validate_warehouse() @@ -279,3 +279,8 @@ class BuyingController(StockController): (", ".join((["%s"]*len(item_codes))),), item_codes)] return self._purchase_items + + + def is_item_table_empty(self): + if not len(self.doclist.get({"parentfield": self.fname})): + webnotes.throw(_("Item table can not be blank")) \ No newline at end of file diff --git a/manufacturing/doctype/production_order/production_order.py b/manufacturing/doctype/production_order/production_order.py index 36cbc646987..9d4ff32e2f7 100644 --- a/manufacturing/doctype/production_order/production_order.py +++ b/manufacturing/doctype/production_order/production_order.py @@ -69,7 +69,7 @@ class DocType: where parent = %s and item_code = %s""", (self.doc.sales_order, self.doc.production_item))[0][0] # get qty from Packing Item table - dnpi_qty = webnotes.conn.sql("""select sum(qty) from `tabDelivery Note Packing Item` + dnpi_qty = webnotes.conn.sql("""select sum(qty) from `tabPacked Item` where parent = %s and parenttype = 'Sales Order' and item_code = %s""", (self.doc.sales_order, self.doc.production_item))[0][0] # total qty in SO diff --git a/patches/october_2013/p06_rename_packing_list_doctype.py b/patches/october_2013/p06_rename_packing_list_doctype.py index a7a11e460d7..d7c5c123a2e 100644 --- a/patches/october_2013/p06_rename_packing_list_doctype.py +++ b/patches/october_2013/p06_rename_packing_list_doctype.py @@ -14,7 +14,8 @@ def execute(): webnotes.reload_doc("stock", "doctype", "packed_item") - os.system("rm -rf app/stock/doctype/delivery_note_packing_item") + if os.path.exists("app/stock/doctype/delivery_note_packing_item"): + os.system("rm -rf app/stock/doctype/delivery_note_packing_item") if webnotes.conn.exists("DocType", "Delivery Note Packing Item"): webnotes.delete_doc("DocType", "Delivery Note Packing Item") \ No newline at end of file diff --git a/stock/doctype/material_request/material_request.py b/stock/doctype/material_request/material_request.py index 7aea3364e4a..4af86dac69b 100644 --- a/stock/doctype/material_request/material_request.py +++ b/stock/doctype/material_request/material_request.py @@ -96,9 +96,6 @@ class DocType(BuyingController): update_bin(args) def on_submit(self): - purchase_controller = webnotes.get_obj("Purchase Common") - purchase_controller.is_item_table_empty(self) - webnotes.conn.set(self.doc,'status','Submitted') self.update_bin(is_submit = 1, is_stopped = 0) diff --git a/stock/doctype/purchase_receipt/purchase_receipt.py b/stock/doctype/purchase_receipt/purchase_receipt.py index 13794067c50..99cbd0be9c3 100644 --- a/stock/doctype/purchase_receipt/purchase_receipt.py +++ b/stock/doctype/purchase_receipt/purchase_receipt.py @@ -227,7 +227,6 @@ class DocType(BuyingController): # on submit def on_submit(self): purchase_controller = webnotes.get_obj("Purchase Common") - purchase_controller.is_item_table_empty(self) # Check for Approving Authority get_obj('Authorization Control').validate_approving_authority(self.doc.doctype, self.doc.company, self.doc.grand_total) From 70d7c481e9083ea817da79ab632e30e5b222fab7 Mon Sep 17 00:00:00 2001 From: Rushabh Mehta Date: Fri, 18 Oct 2013 17:23:50 +0530 Subject: [PATCH 191/200] [naming series] create, remove Property Setters to set naming fixes webnotes/erpnext#854 --- .../buying_settings/buying_settings.py | 5 ++++- buying/doctype/supplier/supplier.js | 5 +---- hr/doctype/employee/employee.py | 4 ---- hr/doctype/hr_settings/hr_settings.py | 14 ++++++++---- .../p09_update_naming_series_settings.py | 10 +++++++++ patches/patch_list.py | 1 + public/js/utils.js | 2 +- selling/doctype/customer/customer.js | 5 +---- selling/doctype/customer/customer.txt | 22 +++++++++---------- .../selling_settings/selling_settings.py | 4 ++++ setup/doctype/naming_series/naming_series.py | 17 ++++++++++++++ stock/doctype/item/item.js | 6 +---- .../doctype/stock_settings/stock_settings.py | 6 +++++ 13 files changed, 67 insertions(+), 34 deletions(-) create mode 100644 patches/october_2013/p09_update_naming_series_settings.py diff --git a/buying/doctype/buying_settings/buying_settings.py b/buying/doctype/buying_settings/buying_settings.py index 3f4f96da6f3..efca33932d7 100644 --- a/buying/doctype/buying_settings/buying_settings.py +++ b/buying/doctype/buying_settings/buying_settings.py @@ -13,4 +13,7 @@ class DocType: def validate(self): for key in ["supplier_type", "supp_master_name", "maintain_same_rate", "buying_price_list"]: webnotes.conn.set_default(key, self.doc.fields.get(key, "")) - \ No newline at end of file + + from setup.doctype.naming_series.naming_series import set_by_naming_series + set_by_naming_series("Supplier", "supplier_name", + self.doc.get("supp_master_name")=="Naming Series", hide_name_field=False) diff --git a/buying/doctype/supplier/supplier.js b/buying/doctype/supplier/supplier.js index 75542c82579..ebe4e0e513e 100644 --- a/buying/doctype/supplier/supplier.js +++ b/buying/doctype/supplier/supplier.js @@ -9,10 +9,7 @@ cur_frm.cscript.onload = function(doc,dt,dn){ cur_frm.cscript.refresh = function(doc,dt,dn) { cur_frm.cscript.make_dashboard(doc); - if(sys_defaults.supp_master_name == 'Supplier Name') - hide_field('naming_series'); - else - unhide_field('naming_series'); + erpnext.hide_naming_series(); if(doc.__islocal){ hide_field(['address_html','contact_html']); diff --git a/hr/doctype/employee/employee.py b/hr/doctype/employee/employee.py index b46123a6d1f..56dfb357660 100644 --- a/hr/doctype/employee/employee.py +++ b/hr/doctype/employee/employee.py @@ -20,12 +20,8 @@ class DocType: webnotes.throw(_("Please setup Employee Naming System in Human Resource > HR Settings")) else: if naming_method=='Naming Series': - if not self.doc.naming_series: - webnotes.throw(_("Please select Naming Neries")) self.doc.name = make_autoname(self.doc.naming_series + '.####') elif naming_method=='Employee Number': - if not self.doc.employee_number: - webnotes.throw(_("Please enter Employee Number")) self.doc.name = self.doc.employee_number self.doc.employee = self.doc.name diff --git a/hr/doctype/hr_settings/hr_settings.py b/hr/doctype/hr_settings/hr_settings.py index 101905c57b4..20edd1642d0 100644 --- a/hr/doctype/hr_settings/hr_settings.py +++ b/hr/doctype/hr_settings/hr_settings.py @@ -13,12 +13,18 @@ class DocType: self.doc, self.doclist = d, dl def validate(self): - self.original_stop_birthday_reminders = cint(webnotes.conn.get_value("HR Settings", - None, "stop_birthday_reminders")) + self.update_birthday_reminders() + + from setup.doctype.naming_series.naming_series import set_by_naming_series + set_by_naming_series("Employee", "employee_number", + self.doc.get("emp_created_by")=="Naming Series", hide_name_field=True) - def on_update(self): + def update_birthday_reminders(self): + original_stop_birthday_reminders = cint(webnotes.conn.get_value("HR Settings", + None, "stop_birthday_reminders")) + # reset birthday reminders - if cint(self.doc.stop_birthday_reminders) != self.original_stop_birthday_reminders: + if cint(self.doc.stop_birthday_reminders) != original_stop_birthday_reminders: webnotes.conn.sql("""delete from `tabEvent` where repeat_on='Every Year' and ref_type='Employee'""") if not self.doc.stop_birthday_reminders: diff --git a/patches/october_2013/p09_update_naming_series_settings.py b/patches/october_2013/p09_update_naming_series_settings.py new file mode 100644 index 00000000000..57b48dae2c9 --- /dev/null +++ b/patches/october_2013/p09_update_naming_series_settings.py @@ -0,0 +1,10 @@ +# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. +# License: GNU General Public License v3. See license.txt + +from __future__ import unicode_literals +import webnotes + +def execute(): + # reset property setters for series + for name in ("Stock Settings", "Selling Settings", "Buying Settings", "HR Settings"): + webnotes.bean(name, name).save() \ No newline at end of file diff --git a/patches/patch_list.py b/patches/patch_list.py index 78dc155307b..5e03664f46a 100644 --- a/patches/patch_list.py +++ b/patches/patch_list.py @@ -228,4 +228,5 @@ patch_list = [ "patches.october_2013.repost_planned_qty", "patches.october_2013.p06_rename_packing_list_doctype", "execute:webnotes.delete_doc('DocType', 'Sales Common')", + "patches.october_2013.p09_update_naming_series_settings", ] \ No newline at end of file diff --git a/public/js/utils.js b/public/js/utils.js index 6879b69e7a1..ddeca269b05 100644 --- a/public/js/utils.js +++ b/public/js/utils.js @@ -13,7 +13,7 @@ $.extend(erpnext, { }, hide_naming_series: function() { - if(cur_frm.fields_dict.naming_series) { + if(cur_frm.fields_dict.naming_series && !wn.meta.get_docfield(cur_frm.doctype, "naming_series")) { cur_frm.toggle_display("naming_series", cur_frm.doc.__islocal?true:false); } }, diff --git a/selling/doctype/customer/customer.js b/selling/doctype/customer/customer.js index a38ab9cbf00..a703eed53dc 100644 --- a/selling/doctype/customer/customer.js +++ b/selling/doctype/customer/customer.js @@ -20,10 +20,7 @@ cur_frm.add_fetch('default_sales_partner','commission_rate','default_commission_ cur_frm.cscript.refresh = function(doc,dt,dn) { cur_frm.cscript.setup_dashboard(doc); - if(sys_defaults.cust_master_name == 'Customer Name') - hide_field('naming_series'); - else - unhide_field('naming_series'); + erpnext.hide_naming_series(); if(doc.__islocal){ hide_field(['address_html','contact_html']); diff --git a/selling/doctype/customer/customer.txt b/selling/doctype/customer/customer.txt index b25c0bd32bf..5d3a508d4ef 100644 --- a/selling/doctype/customer/customer.txt +++ b/selling/doctype/customer/customer.txt @@ -2,7 +2,7 @@ { "creation": "2013-06-11 14:26:44", "docstatus": 0, - "modified": "2013-09-10 10:50:50", + "modified": "2013-10-18 16:49:20", "modified_by": "Administrator", "owner": "Administrator" }, @@ -48,6 +48,16 @@ "permlevel": 0, "reqd": 0 }, + { + "doctype": "DocField", + "fieldname": "naming_series", + "fieldtype": "Select", + "label": "Document Numbering Series", + "no_copy": 1, + "options": "\nCUST\nCUSTMUM", + "permlevel": 0, + "print_hide": 0 + }, { "doctype": "DocField", "fieldname": "customer_name", @@ -76,16 +86,6 @@ "permlevel": 0, "reqd": 1 }, - { - "doctype": "DocField", - "fieldname": "naming_series", - "fieldtype": "Select", - "label": "Document Numbering Series", - "no_copy": 1, - "options": "\nCUST\nCUSTMUM", - "permlevel": 0, - "print_hide": 0 - }, { "description": "Fetch lead which will be converted into customer.", "doctype": "DocField", diff --git a/selling/doctype/selling_settings/selling_settings.py b/selling/doctype/selling_settings/selling_settings.py index 93866528e02..620721df06d 100644 --- a/selling/doctype/selling_settings/selling_settings.py +++ b/selling/doctype/selling_settings/selling_settings.py @@ -14,3 +14,7 @@ class DocType: for key in ["cust_master_name", "customer_group", "territory", "maintain_same_sales_rate", "editable_price_list_rate", "selling_price_list"]: webnotes.conn.set_default(key, self.doc.fields.get(key, "")) + + from setup.doctype.naming_series.naming_series import set_by_naming_series + set_by_naming_series("Customer", "customer_name", + self.doc.get("cust_master_name")=="Naming Series", hide_name_field=False) diff --git a/setup/doctype/naming_series/naming_series.py b/setup/doctype/naming_series/naming_series.py index 4e85b15f6d9..527ec6e852a 100644 --- a/setup/doctype/naming_series/naming_series.py +++ b/setup/doctype/naming_series/naming_series.py @@ -134,3 +134,20 @@ class DocType: msgprint("Series Updated Successfully") else: msgprint("Please select prefix first") + +def set_by_naming_series(doctype, fieldname, naming_series, hide_name_field=True): + from core.doctype.property_setter.property_setter import make_property_setter + if naming_series: + make_property_setter(doctype, "naming_series", "hidden", 0, "Check") + make_property_setter(doctype, "naming_series", "reqd", 1, "Check") + if hide_name_field: + make_property_setter(doctype, fieldname, "reqd", 0, "Check") + make_property_setter(doctype, fieldname, "hidden", 1, "Check") + else: + make_property_setter(doctype, "naming_series", "reqd", 0, "Check") + make_property_setter(doctype, "naming_series", "hidden", 1, "Check") + if hide_name_field: + make_property_setter(doctype, fieldname, "hidden", 0, "Check") + make_property_setter(doctype, fieldname, "reqd", 1, "Check") + + \ No newline at end of file diff --git a/stock/doctype/item/item.js b/stock/doctype/item/item.js index d0b8492ddd9..daa8e2372b4 100644 --- a/stock/doctype/item/item.js +++ b/stock/doctype/item/item.js @@ -6,11 +6,7 @@ cur_frm.cscript.refresh = function(doc) { // read only if any stock ledger entry exists cur_frm.cscript.make_dashboard() - - cur_frm.toggle_display("naming_series", sys_defaults.item_naming_by=="Naming Series" - && doc.__islocal) - cur_frm.toggle_display("item_code", sys_defaults.item_naming_by!="Naming Series" - && doc.__islocal) + erpnext.hide_naming_series(); if(!doc.__islocal && doc.show_in_website) { cur_frm.add_custom_button("View In Website", function() { diff --git a/stock/doctype/stock_settings/stock_settings.py b/stock/doctype/stock_settings/stock_settings.py index bc7dcba4fdf..e4572578cae 100644 --- a/stock/doctype/stock_settings/stock_settings.py +++ b/stock/doctype/stock_settings/stock_settings.py @@ -6,6 +6,7 @@ from __future__ import unicode_literals import webnotes + class DocType: def __init__(self, d, dl): self.doc, self.doclist = d, dl @@ -14,3 +15,8 @@ class DocType: for key in ["item_naming_by", "item_group", "stock_uom", "allow_negative_stock"]: webnotes.conn.set_default(key, self.doc.fields.get(key, "")) + + from setup.doctype.naming_series.naming_series import set_by_naming_series + set_by_naming_series("Item", "item_code", + self.doc.get("item_naming_by")=="Naming Series", hide_name_field=True) + From a137e8cf0320ac22996ca9f7cb58690e3f1e5062 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A1rbara=20Perretti?= Date: Fri, 18 Oct 2013 14:25:29 -0300 Subject: [PATCH 192/200] Fix translate setup/doctype/company/company.js --- setup/doctype/company/company.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup/doctype/company/company.js b/setup/doctype/company/company.js index 2f1d6624f4c..217cf865677 100644 --- a/setup/doctype/company/company.js +++ b/setup/doctype/company/company.js @@ -31,7 +31,7 @@ cur_frm.cscript.company_name = function(doc){ cur_frm.cscript.abbr = function(doc){ if(doc.abbr && cur_frm.cscript.has_special_chars(doc.abbr)){ - msgprint(""wn._("Special Characters ")+"! @ # $ % ^ * + = - [ ] ' ; , / { } | : < > ?" + + msgprint(""+wn._("Special Characters ")+"! @ # $ % ^ * + = - [ ] ' ; , / { } | : < > ?" + wn._("are not allowed for")+ "\nAbbr " + doc.abbr +"") doc.abbr = ''; refresh_field('abbr'); From f3f496a8d742c81cb9edbca8780c37e470dbd0a0 Mon Sep 17 00:00:00 2001 From: Rushabh Mehta Date: Mon, 21 Oct 2013 15:24:49 +0530 Subject: [PATCH 193/200] [naming series] [minor] [fix] --- setup/doctype/naming_series/naming_series.py | 16 ++++++++++++++- support/doctype/newsletter/newsletter.py | 21 +++----------------- 2 files changed, 18 insertions(+), 19 deletions(-) diff --git a/setup/doctype/naming_series/naming_series.py b/setup/doctype/naming_series/naming_series.py index 527ec6e852a..51ca4379a9d 100644 --- a/setup/doctype/naming_series/naming_series.py +++ b/setup/doctype/naming_series/naming_series.py @@ -140,14 +140,28 @@ def set_by_naming_series(doctype, fieldname, naming_series, hide_name_field=True if naming_series: make_property_setter(doctype, "naming_series", "hidden", 0, "Check") make_property_setter(doctype, "naming_series", "reqd", 1, "Check") + + # set values for mandatory + webnotes.conn.sql("""update `tab{doctype}` set naming_series={s} where + ifnull(naming_series, '')=''""".format(doctyp=doctype, s="%s"), get_default_naming_series(doctype)) + if hide_name_field: make_property_setter(doctype, fieldname, "reqd", 0, "Check") make_property_setter(doctype, fieldname, "hidden", 1, "Check") else: make_property_setter(doctype, "naming_series", "reqd", 0, "Check") make_property_setter(doctype, "naming_series", "hidden", 1, "Check") + if hide_name_field: make_property_setter(doctype, fieldname, "hidden", 0, "Check") make_property_setter(doctype, fieldname, "reqd", 1, "Check") + + # set values for mandatory + webnotes.conn.sql("""update `tab{doctype}` set `{fieldname}`=`name` where + ifnull({fieldname}, '')=''""".format(doctyp=doctype, fieldname=fieldname)) - \ No newline at end of file +def get_default_naming_series(doctype): + from webnotes.model.doctype import get_property + naming_series = get_property(doctype, "options", "naming_series") + naming_series = naming_series.split("\n") + return naming_series[0] or naming_series[1] \ No newline at end of file diff --git a/support/doctype/newsletter/newsletter.py b/support/doctype/newsletter/newsletter.py index 8e45768b353..b480b7dd88a 100644 --- a/support/doctype/newsletter/newsletter.py +++ b/support/doctype/newsletter/newsletter.py @@ -111,6 +111,7 @@ def get_lead_options(): def create_lead(email_id): """create a lead if it does not exist""" from email.utils import parseaddr + from webnotes.model.doc import get_default_naming_series real_name, email_id = parseaddr(email_id) if webnotes.conn.get_value("Lead", {"email_id": email_id}): @@ -121,24 +122,8 @@ def create_lead(email_id): "email_id": email_id, "lead_name": real_name or email_id, "status": "Contacted", - "naming_series": get_lead_naming_series(), + "naming_series": get_default_naming_series("Lead"), "company": webnotes.conn.get_default("company"), "source": "Email" }) - lead.insert() - -def get_lead_naming_series(): - """gets lead's default naming series""" - lead_naming_series = None - naming_series_field = webnotes.get_doctype("Lead").get_field("naming_series") - if naming_series_field.default: - lead_naming_series = naming_series_field.default - else: - latest_naming_series = webnotes.conn.sql("""select naming_series - from `tabLead` order by creation desc limit 1""") - if latest_naming_series: - lead_naming_series = latest_naming_series[0][0] - else: - lead_naming_series = filter(None, naming_series_field.options.split("\n"))[0] - - return lead_naming_series + lead.insert() \ No newline at end of file From 1abbebad7bf9ef68677db35fd7b066d17c7f06f1 Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Mon, 21 Oct 2013 16:29:10 +0530 Subject: [PATCH 194/200] [fix] [minor] naming series patch --- setup/doctype/naming_series/naming_series.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/setup/doctype/naming_series/naming_series.py b/setup/doctype/naming_series/naming_series.py index 51ca4379a9d..36d6a843000 100644 --- a/setup/doctype/naming_series/naming_series.py +++ b/setup/doctype/naming_series/naming_series.py @@ -143,7 +143,7 @@ def set_by_naming_series(doctype, fieldname, naming_series, hide_name_field=True # set values for mandatory webnotes.conn.sql("""update `tab{doctype}` set naming_series={s} where - ifnull(naming_series, '')=''""".format(doctyp=doctype, s="%s"), get_default_naming_series(doctype)) + ifnull(naming_series, '')=''""".format(doctype=doctype, s="%s"), get_default_naming_series(doctype)) if hide_name_field: make_property_setter(doctype, fieldname, "reqd", 0, "Check") @@ -158,7 +158,7 @@ def set_by_naming_series(doctype, fieldname, naming_series, hide_name_field=True # set values for mandatory webnotes.conn.sql("""update `tab{doctype}` set `{fieldname}`=`name` where - ifnull({fieldname}, '')=''""".format(doctyp=doctype, fieldname=fieldname)) + ifnull({fieldname}, '')=''""".format(doctype=doctype, fieldname=fieldname)) def get_default_naming_series(doctype): from webnotes.model.doctype import get_property From 213da21332c3a01a338cd541299cca223817cace Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Mon, 21 Oct 2013 18:32:56 +0530 Subject: [PATCH 195/200] [fix] [minor] naming for amendment --- accounts/doctype/journal_voucher/journal_voucher.js | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/accounts/doctype/journal_voucher/journal_voucher.js b/accounts/doctype/journal_voucher/journal_voucher.js index a6aa007b129..95adc8ecacf 100644 --- a/accounts/doctype/journal_voucher/journal_voucher.js +++ b/accounts/doctype/journal_voucher/journal_voucher.js @@ -12,10 +12,13 @@ erpnext.accounts.JournalVoucher = wn.ui.form.Controller.extend({ load_defaults: function() { if(this.frm.doc.__islocal && this.frm.doc.company) { wn.model.set_default_values(this.frm.doc); - $.each(wn.model.get_doclist(this.frm.doc.doctype, this.frm.doc.name, {parentfield: "entries"}), - function(i, jvd) { wn.model.set_default_values(jvd); }); + $.each(wn.model.get_doclist(this.frm.doc.doctype, + this.frm.doc.name, {parentfield: "entries"}), function(i, jvd) { + wn.model.set_default_values(jvd); + } + ); - this.frm.doc.posting_date = get_today(); + if(!this.frm.doc.amended_from) this.frm.doc.posting_date = get_today(); } }, From 8833c52c025baf246d2b22e0d836f8c8182d51d7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A1rbara=20Perretti?= Date: Mon, 21 Oct 2013 17:39:37 -0200 Subject: [PATCH 196/200] Fix translate public/js/startup.js --- public/js/startup.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/public/js/startup.js b/public/js/startup.js index 76b77148877..ecb23dae78b 100644 --- a/public/js/startup.js +++ b/public/js/startup.js @@ -26,7 +26,7 @@ erpnext.startup.show_expiry_banner = function() { var msg = ""; if (0 <= diff && diff <= 10) { var expiry_string = diff==0 ? "today" : repl("in %(diff)s day(s)", { diff: diff }); - msg = repl(wn._('Your ERPNext subscription will expire %(expiry_string)s. %(payment_link)s'), + msg = repl(wn._('Your ERPNext subscription will')+'expire %(expiry_string)s. %(payment_link)s', { expiry_string: expiry_string, payment_link: payment_link }); } else if (diff < 0) { msg = repl(wn._('This ERPNext subscription')+''+wn._('has expired')+'. %(payment_link)s'), {payment_link: payment_link}); From d43c6bfdfb709690cf36ff471e7234b3b5d202cd Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Thu, 24 Oct 2013 11:57:02 +0530 Subject: [PATCH 197/200] [fix] [merge conflict] --- .../purchase_taxes_and_charges_master.js | 17 ----------------- .../sales_taxes_and_charges_master.js | 18 ------------------ selling/doctype/opportunity/opportunity.js | 15 ++++----------- selling/doctype/quotation/quotation.js | 14 ++++---------- 4 files changed, 8 insertions(+), 56 deletions(-) diff --git a/accounts/doctype/purchase_taxes_and_charges_master/purchase_taxes_and_charges_master.js b/accounts/doctype/purchase_taxes_and_charges_master/purchase_taxes_and_charges_master.js index 294923c14fa..9e497e4ef54 100644 --- a/accounts/doctype/purchase_taxes_and_charges_master/purchase_taxes_and_charges_master.js +++ b/accounts/doctype/purchase_taxes_and_charges_master/purchase_taxes_and_charges_master.js @@ -136,23 +136,6 @@ cur_frm.fields_dict['purchase_tax_details'].grid.get_field("cost_center").get_qu } } -<<<<<<< HEAD -cur_frm.cscript.account_head = function(doc, cdt, cdn) { - var d = locals[cdt][cdn]; - if(!d.charge_type && d.account_head){ - alert(wn._("Please select Charge Type first")); - validated = false; - d.account_head = ''; - } - else if(d.account_head && d.charge_type) { - arg = "{'charge_type' : '" + d.charge_type + "', 'account_head' : '" + d.account_head + "'}"; - return get_server_fields('get_rate', arg, 'purchase_tax_details', doc, cdt, cdn, 1); - } - refresh_field('account_head',d.name,'purchase_tax_details'); -} - -======= ->>>>>>> f146e8b7f52a3e46e335c0fefd92c347717b370b cur_frm.cscript.rate = function(doc, cdt, cdn) { var d = locals[cdt][cdn]; if(!d.charge_type && d.rate) { diff --git a/accounts/doctype/sales_taxes_and_charges_master/sales_taxes_and_charges_master.js b/accounts/doctype/sales_taxes_and_charges_master/sales_taxes_and_charges_master.js index 0e623a1dc7e..9841783f76d 100644 --- a/accounts/doctype/sales_taxes_and_charges_master/sales_taxes_and_charges_master.js +++ b/accounts/doctype/sales_taxes_and_charges_master/sales_taxes_and_charges_master.js @@ -145,24 +145,6 @@ cur_frm.fields_dict['other_charges'].grid.get_field("cost_center").get_query = f } } -<<<<<<< HEAD - -cur_frm.cscript.account_head = function(doc, cdt, cdn) { - var d = locals[cdt][cdn]; - if(!d.charge_type && d.account_head){ - alert(wn._("Please select Charge Type first")); - validated = false; - d.account_head = ''; - } - else if(d.account_head && d.charge_type) { - arg = "{'charge_type' : '" + d.charge_type +"', 'account_head' : '" + d.account_head + "'}"; - return get_server_fields('get_rate', arg, 'other_charges', doc, cdt, cdn, 1); - } - refresh_field('account_head',d.name,'other_charges'); -} - -======= ->>>>>>> f146e8b7f52a3e46e335c0fefd92c347717b370b cur_frm.cscript.rate = function(doc, cdt, cdn) { var d = locals[cdt][cdn]; if(!d.charge_type && d.rate) { diff --git a/selling/doctype/opportunity/opportunity.js b/selling/doctype/opportunity/opportunity.js index e65ef509510..75fde277ec7 100644 --- a/selling/doctype/opportunity/opportunity.js +++ b/selling/doctype/opportunity/opportunity.js @@ -101,21 +101,14 @@ $.extend(cur_frm.cscript, new erpnext.selling.Opportunity({frm: cur_frm})); cur_frm.cscript.refresh = function(doc, cdt, cdn){ erpnext.hide_naming_series(); - cur_frm.clear_custom_buttons(); -<<<<<<< HEAD - if(doc.docstatus === 1 && doc.status!=="Opportunity Lost") { - cur_frm.add_custom_button( wn._('Create Quotation'), cur_frm.cscript.create_quotation); - cur_frm.add_custom_button(wn._('Opportunity Lost'), cur_frm.cscript['Declare Opportunity Lost']); - cur_frm.add_custom_button(wn._('Send SMS'), cur_frm.cscript.send_sms); -======= + if(doc.docstatus === 1 && doc.status!=="Lost") { - cur_frm.add_custom_button('Create Quotation', cur_frm.cscript.create_quotation); + cur_frm.add_custom_button(wn._('Create Quotation'), cur_frm.cscript.create_quotation); if(doc.status!=="Quotation") { - cur_frm.add_custom_button('Opportunity Lost', cur_frm.cscript['Declare Opportunity Lost']); + cur_frm.add_custom_button(wn._('Opportunity Lost'), cur_frm.cscript['Declare Opportunity Lost']); } - cur_frm.add_custom_button('Send SMS', cur_frm.cscript.send_sms); ->>>>>>> f146e8b7f52a3e46e335c0fefd92c347717b370b + cur_frm.add_custom_button(wn._('Send SMS'), cur_frm.cscript.send_sms); } cur_frm.toggle_display("contact_info", doc.customer || doc.lead); diff --git a/selling/doctype/quotation/quotation.js b/selling/doctype/quotation/quotation.js index 776167229d0..f890b28d760 100644 --- a/selling/doctype/quotation/quotation.js +++ b/selling/doctype/quotation/quotation.js @@ -25,17 +25,12 @@ erpnext.selling.QuotationController = erpnext.selling.SellingController.extend({ refresh: function(doc, dt, dn) { this._super(doc, dt, dn); -<<<<<<< HEAD - if(doc.docstatus == 1 && doc.status!=='Order Lost') { - cur_frm.add_custom_button(wn._('Make Sales Order'), cur_frm.cscript['Make Sales Order']); - if(doc.status!=="Order Confirmed") { - cur_frm.add_custom_button(wn._('Set as Lost'), cur_frm.cscript['Declare Order Lost']); -======= if(doc.docstatus == 1 && doc.status!=='Lost') { - cur_frm.add_custom_button('Make Sales Order', cur_frm.cscript['Make Sales Order']); + cur_frm.add_custom_button(wn._('Make Sales Order'), + cur_frm.cscript['Make Sales Order']); if(doc.status!=="Ordered") { - cur_frm.add_custom_button('Set as Lost', cur_frm.cscript['Declare Order Lost']); ->>>>>>> f146e8b7f52a3e46e335c0fefd92c347717b370b + cur_frm.add_custom_button(wn._('Set as Lost'), + cur_frm.cscript['Declare Order Lost']); } cur_frm.add_custom_button(wn._('Send SMS'), cur_frm.cscript.send_sms); } @@ -57,7 +52,6 @@ erpnext.selling.QuotationController = erpnext.selling.SellingController.extend({ }) }); } - if (!doc.__islocal) { cur_frm.communication_view = new wn.views.CommunicationList({ From 05ff7cbd9077ea307a7fb0eb246cf4efe366c1bb Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Thu, 24 Oct 2013 14:50:03 +0530 Subject: [PATCH 198/200] [fix] [minor] translation issue in startup --- public/js/startup.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/public/js/startup.js b/public/js/startup.js index ecb23dae78b..3af847dd7f1 100644 --- a/public/js/startup.js +++ b/public/js/startup.js @@ -29,7 +29,7 @@ erpnext.startup.show_expiry_banner = function() { msg = repl(wn._('Your ERPNext subscription will')+'expire %(expiry_string)s. %(payment_link)s', { expiry_string: expiry_string, payment_link: payment_link }); } else if (diff < 0) { - msg = repl(wn._('This ERPNext subscription')+''+wn._('has expired')+'. %(payment_link)s'), {payment_link: payment_link}); + msg = repl(wn._('This ERPNext subscription')+''+wn._('has expired')+'. %(payment_link)s', {payment_link: payment_link}); } if(msg) wn.ui.toolbar.show_banner(msg); From 7fa2ec40e18f7cffb6ba84e99c65201c6e399294 Mon Sep 17 00:00:00 2001 From: Anand Doshi Date: Thu, 24 Oct 2013 20:47:35 +0530 Subject: [PATCH 199/200] Removed Update Manager --- patches/october_2013/p04_wsgi_migration.py | 5 ++++- setup/page/setup/setup.js | 2 +- setup/page/setup/setup.py | 2 -- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/patches/october_2013/p04_wsgi_migration.py b/patches/october_2013/p04_wsgi_migration.py index ca73516c25a..d374f4ee171 100644 --- a/patches/october_2013/p04_wsgi_migration.py +++ b/patches/october_2013/p04_wsgi_migration.py @@ -27,4 +27,7 @@ def execute(): for file_path in (("js", "wn-web.js"), ("css", "wn-web.css")): file_path = os.path.join(base_path, "public", *file_path) if os.path.exists(file_path): - os.remove(file_path) \ No newline at end of file + os.remove(file_path) + + # Remove update app page + webnotes.delete_doc("Page", "update-manager") diff --git a/setup/page/setup/setup.js b/setup/page/setup/setup.js index 0127a2a3f09..ed55eb5ca95 100644 --- a/setup/page/setup/setup.js +++ b/setup/page/setup/setup.js @@ -180,7 +180,7 @@ wn.pages.Setup.make = function(wrapper) { if(r.message) { body.empty(); if(wn.boot.expires_on) { - $(body).prepend("
    "+wn.("Account expires on") + $(body).prepend("
    "+wn._("Account expires on") + wn.datetime.global_date_format(wn.boot.expires_on) + "
    "); } diff --git a/setup/page/setup/setup.py b/setup/page/setup/setup.py index 1569ef00da6..caa32efa1d0 100644 --- a/setup/page/setup/setup.py +++ b/setup/page/setup/setup.py @@ -226,8 +226,6 @@ items = [ "title": "System Administration", "icon": "icon-cog" }, - { "title": "Update ERPNext", - "route": "update-manager", "type": "Link", "icon": "icon-rss" }, { "title": "Manage 3rd Party Backups", "route": "Form/Backup Manager", "type": "Link", "icon": "icon-cloud" }, { "title": "System Scheduler Errors", From fe44d27d7f29cf6a9c16f553af05fa079a949a87 Mon Sep 17 00:00:00 2001 From: Pratik Vyas Date: Thu, 24 Oct 2013 23:59:53 +0530 Subject: [PATCH 200/200] new install_erpnext.py, first cut --- install_erpnext.py | 139 ++++++++++++--------------------------------- 1 file changed, 37 insertions(+), 102 deletions(-) diff --git a/install_erpnext.py b/install_erpnext.py index 7f3b8c3b655..139458c01be 100644 --- a/install_erpnext.py +++ b/install_erpnext.py @@ -5,15 +5,36 @@ from __future__ import unicode_literals import os, sys -apache_user = None is_redhat = is_debian = None root_password = None +requirements = [ + "MySQL-python", + "pytz==2013b", + "python-dateutil", + "jinja2", + "markdown2", + "termcolor", + "python-memcached", + "requests", + "chardet", + "dropbox", + "google-api-python-client ", + "pygeoip" +] + def install(install_path=None): + if os.getuid() != 0: + raise Exception, "Please run this script as root" + install_pre_requisites() + + if os.environ.get('SUDO_UID'): + os.setuid(int(os.environ.get('SUDO_UID'))) if not install_path: install_path = os.getcwd() + setup_folders(install_path) install_erpnext(install_path) post_install(install_path) @@ -44,7 +65,7 @@ def validate_install(): # check python version python_version = sys.version.split(" ")[0] print "Python Version =", python_version - if not (python_version and int(python_version.split(".")[0])==2 and int(python_version.split(".")[1]) >= 6): + if not (python_version and int(python_version.split(".")[0])==2 and int(python_version.split(".")[1]) >= 7): raise Exception, "Hey! ERPNext needs Python version to be 2.6+" # check distribution @@ -59,7 +80,7 @@ def validate_install(): return is_redhat, is_debian def install_using_yum(): - packages = "python python-setuptools gcc python-devel MySQL-python httpd git memcached ntp vim-enhanced screen" + packages = "python python-setuptools gcc python-devel MySQL-python git memcached ntp vim-enhanced screen" print "-"*80 print "Installing Packages: (This may take some time)" @@ -92,9 +113,6 @@ def install_using_yum(): def update_config_for_redhat(): import re - global apache_user - apache_user = "apache" - # update memcache user with open("/etc/sysconfig/memcached", "r") as original: memcached_conf = original.read() @@ -108,7 +126,7 @@ def update_config_for_redhat(): def install_using_apt(): exec_in_shell("apt-get update") - packages = "python python-setuptools python-dev build-essential python-pip python-mysqldb apache2 git memcached ntp vim screen htop" + packages = "python python-setuptools python-dev build-essential python-pip python-mysqldb git memcached ntp vim screen htop" print "-"*80 print "Installing Packages: (This may take some time)" print packages @@ -123,8 +141,6 @@ def install_using_apt(): update_config_for_debian() def update_config_for_debian(): - global apache_user - apache_user = "www-data" # update memcache user with open("/etc/memcached.conf", "r") as original: @@ -132,14 +148,10 @@ def update_config_for_debian(): with open("/etc/memcached.conf", "w") as modified: modified.write(memcached_conf.replace("-u memcache", "-u %s" % apache_user)) - exec_in_shell("a2enmod rewrite") - - for service in ("mysql", "apache2", "memcached", "ntpd"): + for service in ("mysql", "memcached", "ntpd"): exec_in_shell("service %s restart" % service) def install_python_modules(): - python_modules = "pytz python-dateutil jinja2 markdown2 termcolor python-memcached requests chardet dropbox google-api-python-client pygeoip" - print "-"*80 print "Installing Python Modules: (This may take some time)" print python_modules @@ -151,7 +163,7 @@ def install_python_modules(): exec_in_shell("pip install --upgrade pip") exec_in_shell("pip install --upgrade setuptools") exec_in_shell("pip install --upgrade virtualenv") - exec_in_shell("pip install -q %s" % python_modules) + exec_in_shell("pip install -r {}".format(' '.join(requirements))) def install_erpnext(install_path): print @@ -169,19 +181,15 @@ def install_erpnext(install_path): if not db_name: raise Exception, "Sorry! You must specify ERPNext Database Name" - # install folders and conf - setup_folders(install_path) - setup_conf(install_path, db_name) - # setup paths - sys.path.extend([".", "lib", "app"]) + sys.path = [".", "lib", "app"] + sys.path + import wnf # install database, run patches, update schema - setup_db(install_path, root_password, db_name) - - setup_cron(install_path) - - setup_apache_conf(install_path) + # setup_db(install_path, root_password, db_name) + wnf.install(db_name, root_password=root_password) + + # setup_cron(install_path) def get_root_password(): # ask for root mysql password @@ -200,7 +208,7 @@ def setup_folders(install_path): app = os.path.join(install_path, "app") if not os.path.exists(app): print "Cloning erpnext" - exec_in_shell("cd %s && git clone https://github.com/webnotes/erpnext.git app" % install_path) + exec_in_shell("cd %s && git clone https://github.com/webnotes/erpnext.git app && cd app && git checkout wsgi" % install_path) exec_in_shell("cd app && git config core.filemode false") if not os.path.exists(app): raise Exception, "Couldn't clone erpnext repository" @@ -208,7 +216,7 @@ def setup_folders(install_path): lib = os.path.join(install_path, "lib") if not os.path.exists(lib): print "Cloning wnframework" - exec_in_shell("cd %s && git clone https://github.com/webnotes/wnframework.git lib" % install_path) + exec_in_shell("cd %s && git clone https://github.com/webnotes/wnframework.git lib && cd lib && git checkout wsgi" % install_path) exec_in_shell("cd lib && git config core.filemode false") if not os.path.exists(lib): raise Exception, "Couldn't clone wnframework repository" @@ -238,86 +246,13 @@ def setup_conf(install_path, db_name): return db_password -def setup_db(install_path, root_password, db_name): - from webnotes.install_lib.install import Installer - inst = Installer("root", root_password) - inst.import_from_db(db_name, verbose=1) - - # run patches and sync - exec_in_shell("./lib/wnf.py --patch_sync_build") - -def setup_cron(install_path): - erpnext_cron_entries = [ - "*/3 * * * * cd %s && python lib/wnf.py --run_scheduler >> /var/log/erpnext-sch.log 2>&1" % install_path, - "0 */6 * * * cd %s && python lib/wnf.py --backup >> /var/log/erpnext-backup.log 2>&1" % install_path - ] - - for row in erpnext_cron_entries: - try: - existing_cron = exec_in_shell("crontab -l") - if row not in existing_cron: - exec_in_shell('{ crontab -l; echo "%s"; } | crontab' % row) - except: - exec_in_shell('echo "%s" | crontab' % row) - -def setup_apache_conf(install_path): - apache_conf_content = """Listen 8080 -NameVirtualHost *:8080 - - ServerName localhost - DocumentRoot %s/public/ - - AddHandler cgi-script .cgi .xml .py - AddType application/vnd.ms-fontobject .eot - AddType font/ttf .ttf - AddType font/otf .otf - AddType application/x-font-woff .woff - - - # directory specific options - Options -Indexes +FollowSymLinks +ExecCGI - - # directory's index file - DirectoryIndex web.py - - AllowOverride all - Order Allow,Deny - Allow from all - - # rewrite rule - RewriteEngine on - RewriteCond %%{REQUEST_FILENAME} !-f - RewriteCond %%{REQUEST_FILENAME} !-d - RewriteCond %%{REQUEST_FILENAME} !-l - RewriteRule ^([^/]+)$ /web.py?page=$1 [QSA,L] - -""" % (install_path, install_path) - - new_apache_conf_path = os.path.join(install_path, os.path.basename(install_path)+".conf") - with open(new_apache_conf_path, "w") as apache_conf_file: - apache_conf_file.write(apache_conf_content) - def post_install(install_path): - global apache_user - exec_in_shell("chown -R %s %s" % (apache_user, install_path)) - - apache_conf_filename = os.path.basename(install_path)+".conf" - if is_redhat: - os.symlink(os.path.join(install_path, apache_conf_filename), - os.path.join("/etc/httpd/conf.d", apache_conf_filename)) - exec_in_shell("service httpd restart") - - elif is_debian: - os.symlink(os.path.join(install_path, apache_conf_filename), - os.path.join("/etc/apache2/sites-enabled", apache_conf_filename)) - exec_in_shell("service apache2 restart") - print print "-"*80 - print "To change url domain, run: lib/wnf.py --domain example.com" + print "To start the development server, run lib/wnf.py --serve" print "-"*80 print "Installation complete" - print "Open your browser and go to http://localhost:8080" + print "Open your browser and go to http://localhost:8000" print "Login using username = Administrator and password = admin" def exec_in_shell(cmd):