diff --git a/accounts/doctype/purchase_invoice/purchase_invoice.py b/accounts/doctype/purchase_invoice/purchase_invoice.py index 33fa52c5420..2b84564d5ee 100644 --- a/accounts/doctype/purchase_invoice/purchase_invoice.py +++ b/accounts/doctype/purchase_invoice/purchase_invoice.py @@ -262,13 +262,11 @@ class DocType(BuyingController): if d.purchase_order: submitted = sql("select name from `tabPurchase Order` where docstatus = 1 and name = '%s'" % d.purchase_order) if not submitted: - msgprint("Purchase Order : "+ cstr(d.purchase_order) +" is not submitted") - raise Exception , "Validation Error." + 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) if not submitted: - msgprint("Purchase Receipt : "+ cstr(d.purchase_receipt) +" is not submitted") - raise Exception , "Validation Error." + webnotes.throw("Purchase Receipt : "+ cstr(d.purchase_receipt) +" is not submitted") def update_against_document_in_jv(self): diff --git a/accounts/doctype/sales_invoice/sales_invoice.txt b/accounts/doctype/sales_invoice/sales_invoice.txt index cc5314b276e..2a2a2e1db66 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-08-31 10:11:41", + "modified": "2013-08-31 10:19:01", "modified_by": "Administrator", "owner": "Administrator" }, diff --git a/accounts/report/gross_profit/gross_profit.py b/accounts/report/gross_profit/gross_profit.py index ccc34b51da3..79e389eeea7 100644 --- a/accounts/report/gross_profit/gross_profit.py +++ b/accounts/report/gross_profit/gross_profit.py @@ -4,7 +4,7 @@ from __future__ import unicode_literals import webnotes from webnotes.utils import flt -from stock.utils import get_buying_amount +from stock.utils import get_buying_amount, get_sales_bom_buying_amount def execute(filters=None): if not filters: filters = {} @@ -21,10 +21,15 @@ def execute(filters=None): data = [] for row in source: selling_amount = flt(row.amount) - - buying_amount = get_buying_amount(row.item_code, row.parenttype, row.name, row.item_row, - stock_ledger_entries.get((row.item_code, row.warehouse), []), - item_sales_bom.get(row.parenttype, {}).get(row.name, webnotes._dict())) + + item_sales_bom_map = item_sales_bom.get(row.parenttype, {}).get(row.name, webnotes._dict()) + + if item_sales_bom_map.get(row.item_code): + buying_amount = get_sales_bom_buying_amount(row.item_code, row.warehouse, + row.parenttype, row.name, row.item_row, stock_ledger_entries, item_sales_bom_map) + else: + buying_amount = get_buying_amount(row.parenttype, row.name, row.item_row, + stock_ledger_entries.get((row.item_code, row.warehouse), [])) buying_amount = buying_amount > 0 and buying_amount or 0 diff --git a/config.json b/config.json index 5412b017b24..ef5a1644008 100644 --- a/config.json +++ b/config.json @@ -130,7 +130,7 @@ }, "writers": { "template": "app/website/templates/pages/writers", - "args_method": "website.helpers.blog.get_writers_args" + "args_method": "website.doctype.blogger.blogger.get_writers_args" }, "profile": { "no_cache": true, diff --git a/controllers/buying_controller.py b/controllers/buying_controller.py index 187bcac9823..7e49e60f8a1 100644 --- a/controllers/buying_controller.py +++ b/controllers/buying_controller.py @@ -17,7 +17,6 @@ class BuyingController(StockController): def onload_post_render(self): # contact, address, item details self.set_missing_values() - self.set_taxes("purchase_tax_details", "purchase_other_charges") def validate(self): super(BuyingController, self).validate() @@ -40,6 +39,8 @@ class BuyingController(StockController): self.doc.fields[fieldname] = val self.set_missing_item_details(get_item_details) + if self.doc.fields.get("__islocal"): + self.set_taxes("purchase_tax_details", "purchase_other_charges") def set_supplier_from_item_default(self): if self.meta.get_field("supplier") and not self.doc.supplier: diff --git a/controllers/selling_controller.py b/controllers/selling_controller.py index 4fa97fc0938..1b414221e42 100644 --- a/controllers/selling_controller.py +++ b/controllers/selling_controller.py @@ -14,15 +14,15 @@ class SellingController(StockController): def onload_post_render(self): # contact, address, item details and pos details (if applicable) self.set_missing_values() - self.set_taxes("other_charges", "charge") def set_missing_values(self, for_validate=False): super(SellingController, self).set_missing_values(for_validate) # 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() + if self.doc.fields.get("__islocal"): + self.set_taxes("other_charges", "charge") def set_missing_lead_customer_details(self): if self.doc.customer: diff --git a/docs/docs.community.md b/docs/docs.community.md deleted file mode 100644 index 121a6925d0a..00000000000 --- a/docs/docs.community.md +++ /dev/null @@ -1,14 +0,0 @@ ---- -{ - "_label": "Get Involved" -} ---- -If you are an ERPNext user: - -[https://groups.google.com/group/erpnext-user-forum](https://groups.google.com/group/erpnext-user-forum) - -If you are an ERPNext developer: - -[https://groups.google.com/group/erpnext-developer-forum](https://groups.google.com/group/erpnext-developer-forum) - - diff --git a/docs/docs.md b/docs/docs.md index 378a0b8eb5d..3ed24b75d64 100644 --- a/docs/docs.md +++ b/docs/docs.md @@ -7,28 +7,25 @@ "docs.dev", "docs.download", "docs.community", - "docs.blog", - "docs.about" + "docs.blog" ], "_no_toc": 1 } --- -
-

All-in-One Platform to Manage Your Organization.

-

100% Free and Open Source.

+
+

ERPNext Docs (beta)

+

Open Source ERP Built for The Web.

+

For the main site, go to https://erpnext.com

![Home Screen](img/home.png) +Welcome to the ERPNext Documentation + Community Site + ### What is ERPNext? -ERPNext is an information system that links together an entire organization's operations. It is a software package that offers convenience of managing all the business functions from a single platform. No need of going to different applications to process different requests. No need of saving data in different functional packages. Under one ERP "roof" you can manage Accounting, Warehouse Management, CRM, Human Resources, Supply Chain Management, Sales Management, and Website Design. +ERPNext is an Open Source integrated app (that manages Financial Accounting, Inventory, CRM) that is built grounds up for the web, using some of the latest web technologies and frameworks. ERPNext helps your organization manage Financial Accounting, Inventory, Sales, Purchase, Payroll, Customer Support, E-Commerce all in one platform. Learn more at [https://erpnext.com](https://erpnext.com) -ERPNext is written by Web Notes Technologies keeping small and medium businesses in mind. +### Site Contents -- It gives better access to crucial information as a whole rather than in fragments of different versions. -- It provides comparable financial reports. -- It avoids duplication of reports and redundant data. -- It allows better alignment across cross-functional departments. -- It facilitates Website Design and provides shopping cart facility. -- It gives better deployment on mobiles, tablets, desktops and large screens. \ No newline at end of file +This site contains the full User and Developer Documentation for ERPNext. This is still a work-in-progress. Please feel free to contribute issues and documentation. diff --git a/patches/august_2013/fix_fiscal_year.py b/patches/august_2013/fix_fiscal_year.py new file mode 100644 index 00000000000..67988c440e3 --- /dev/null +++ b/patches/august_2013/fix_fiscal_year.py @@ -0,0 +1,49 @@ +import webnotes + +def execute(): + create_fiscal_years() + + doctypes = webnotes.conn.sql_list("""select parent from tabDocField + where (fieldtype="Link" and options='Fiscal Year') + or (fieldtype="Select" and options='link:Fiscal Year')""") + + for dt in doctypes: + date_fields = webnotes.conn.sql_list("""select fieldname from tabDocField + where parent=%s and fieldtype='Date'""", dt) + + date_field = get_date_field(date_fields, dt) + + if not date_field: + print dt, date_field + else: + webnotes.conn.sql("""update `tab%s` set fiscal_year = + if(%s<='2013-06-30', '2012-2013', '2013-2014')""" % (dt, date_field)) + +def create_fiscal_years(): + fiscal_years = { + "2012-2013": ["2012-07-01", "2013-06-30"], + "2013-2014": ["2013-07-01", "2014-06-30"] + } + + for d in fiscal_years: + webnotes.bean({ + "doctype": "Fiscal Year", + "year": d, + "year_start_date": fiscal_years[d][0], + "is_fiscal_year_closed": "No" + }).insert() + + +def get_date_field(date_fields, dt): + date_field = None + if date_fields: + if "posting_date" in date_fields: + date_field = "posting_date" + elif "transaction_date" in date_fields: + date_field = 'transaction_date' + else: + date_field = date_fields[0] + # print dt, date_fields + + return date_field + \ No newline at end of file diff --git a/selling/doctype/lead/get_leads.py b/selling/doctype/lead/get_leads.py index c376f450a4a..c63468e2f04 100644 --- a/selling/doctype/lead/get_leads.py +++ b/selling/doctype/lead/get_leads.py @@ -9,17 +9,8 @@ from core.doctype.communication.communication import make def add_sales_communication(subject, content, sender, real_name, mail=None, status="Open", date=None): - def set_status(doctype, name): - w = webnotes.bean(doctype, name) - w.ignore_permissions = True - w.doc.status = is_system_user and "Replied" or status - w.doc.save() - if mail: - mail.save_attachments_in_doc(w.doc) - lead_name = webnotes.conn.get_value("Lead", {"email_id": sender}) contact_name = webnotes.conn.get_value("Contact", {"email_id": sender}) - is_system_user = webnotes.conn.get_value("Profile", sender) if not (lead_name or contact_name): # none, create a new Lead @@ -34,14 +25,13 @@ def add_sales_communication(subject, content, sender, real_name, mail=None, lead.insert() lead_name = lead.doc.name - make(content=content, sender=sender, subject=subject, + message = make(content=content, sender=sender, subject=subject, lead=lead_name, contact=contact_name, date=date) - if contact_name: - set_status("Contact", contact_name) - elif lead_name: - set_status("Lead", lead_name) - + if mail: + # save attachments to parent if from mail + bean = webnotes.bean("Contact" if contact_name else "Lead", contact_name or lead_name) + mail.save_attachments_in_doc(bean.doc) class SalesMailbox(POP3Mailbox): def setup(self, args=None): diff --git a/selling/doctype/lead/lead.py b/selling/doctype/lead/lead.py index b2016aa7a90..2bf1aa38457 100644 --- a/selling/doctype/lead/lead.py +++ b/selling/doctype/lead/lead.py @@ -39,17 +39,14 @@ class DocType(SellingController): def validate(self): if self.doc.status == 'Lead Lost' and not self.doc.order_lost_reason: - msgprint("Please Enter Lost Reason under More Info section") - raise Exception + webnotes.throw("Please Enter Lost Reason under More Info section") if self.doc.source == 'Campaign' and not self.doc.campaign_name and session['user'] != 'Guest': - msgprint("Please specify campaign name") - raise Exception + webnotes.throw("Please specify campaign name") if self.doc.email_id: if not validate_email_add(self.doc.email_id): - msgprint('Please enter valid email id.') - raise Exception + webnotes.throw('Please enter valid email id.') def on_update(self): self.check_email_id_is_unique() diff --git a/selling/doctype/sales_common/sales_common.js b/selling/doctype/sales_common/sales_common.js index dea94b8f3d4..5c0c96ad569 100644 --- a/selling/doctype/sales_common/sales_common.js +++ b/selling/doctype/sales_common/sales_common.js @@ -95,7 +95,7 @@ erpnext.selling.SellingController = erpnext.TransactionController.extend({ return{ query : "selling.doctype.sales_common.sales_common.get_batch_no", filters: { - 'item': item.item_code, + 'item_code': item.item_code, 'posting_date': me.frm.doc.posting_date } } diff --git a/selling/doctype/sales_common/sales_common.py b/selling/doctype/sales_common/sales_common.py index 9aac5069163..8271c828740 100644 --- a/selling/doctype/sales_common/sales_common.py +++ b/selling/doctype/sales_common/sales_common.py @@ -340,7 +340,7 @@ def get_batch_no(doctype, txt, searchfield, start, page_len, filters): and batch_no like '%(txt)s' and exists(select * from `tabBatch` where name = sle.batch_no - and expiry_date >= '%(posting_date)s' + and (ifnull(expiry_date, '')='' or expiry_date >= '%(posting_date)s') and docstatus != 2) %(mcond)s group by batch_no having sum(actual_qty) > 0 @@ -353,11 +353,11 @@ def get_batch_no(doctype, txt, searchfield, start, page_len, filters): return webnotes.conn.sql("""select name from tabBatch where docstatus != 2 and item = '%(item_code)s' - and expiry_date >= '%(posting_date)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 + 'page_len': page_len}) diff --git a/selling/doctype/sales_order/sales_order.py b/selling/doctype/sales_order/sales_order.py index 053580f4e0f..795b0bfd34d 100644 --- a/selling/doctype/sales_order/sales_order.py +++ b/selling/doctype/sales_order/sales_order.py @@ -126,8 +126,9 @@ class DocType(SellingController): self.validate_mandatory() self.validate_proj_cust() self.validate_po() - self.validate_uom_is_integer("stock_uom", "qty") + self.validate_uom_is_integer("stock_uom", "qty") self.validate_for_items() + self.validate_warehouse_user() sales_com_obj = get_obj(dt = 'Sales Common') sales_com_obj.check_active_sales_items(self) sales_com_obj.check_conversion_rate(self) @@ -147,6 +148,16 @@ class DocType(SellingController): if not self.doc.billing_status: self.doc.billing_status = 'Not Billed' if not self.doc.delivery_status: self.doc.delivery_status = 'Not Delivered' + + def validate_warehouse_user(self): + from stock.utils import validate_warehouse_user + + 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) + def validate_with_previous_doc(self): super(DocType, self).validate_with_previous_doc(self.tname, { "Quotation": { diff --git a/selling/doctype/sales_order/test_sales_order.py b/selling/doctype/sales_order/test_sales_order.py index 9fd16e8c299..7b72271bec9 100644 --- a/selling/doctype/sales_order/test_sales_order.py +++ b/selling/doctype/sales_order/test_sales_order.py @@ -272,6 +272,29 @@ class TestSalesOrder(unittest.TestCase): self.check_reserved_qty(sbom_test_records[0][2]["item_code"], 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") + + + from stock.utils import UserNotAllowedForWarehouse + so = webnotes.bean(copy = test_records[0]) + so.doc.company = "_Test Company 1" + so.doc.conversion_rate = 0.02 + so.doc.plc_conversion_rate = 0.02 + so.doclist[1].reserved_warehouse = "_Test Warehouse 2 - _TC1" + self.assertRaises(UserNotAllowedForWarehouse, so.insert) + + webnotes.session.user = "test2@example.com" + so.insert() + + webnotes.session.user = "Administrator" + test_dependencies = ["Sales BOM"] test_records = [ diff --git a/stock/doctype/item/item.txt b/stock/doctype/item/item.txt index 8b17aee6bb0..eb05503b329 100644 --- a/stock/doctype/item/item.txt +++ b/stock/doctype/item/item.txt @@ -2,7 +2,7 @@ { "creation": "2013-05-03 10:45:46", "docstatus": 0, - "modified": "2013-08-14 11:46:49", + "modified": "2013-08-30 16:21:38", "modified_by": "Administrator", "owner": "Administrator" }, @@ -35,7 +35,9 @@ "parentfield": "permissions", "parenttype": "DocType", "permlevel": 0, - "read": 1 + "read": 1, + "report": 1, + "submit": 0 }, { "doctype": "DocType", @@ -557,20 +559,6 @@ "read_only": 0, "reqd": 1 }, - { - "default": "No", - "depends_on": "eval:doc.is_sales_item==\"Yes\"", - "description": "Select \"Yes\" if this item is to be sent to a customer or received from a supplier as a sample. Delivery notes and Purchase Receipts will update stock levels but there will be no invoice against this item.", - "doctype": "DocField", - "fieldname": "is_sample_item", - "fieldtype": "Select", - "label": "Allow Samples", - "oldfieldname": "is_sample_item", - "oldfieldtype": "Select", - "options": "Yes\nNo", - "read_only": 0, - "reqd": 1 - }, { "depends_on": "eval:doc.is_sales_item==\"Yes\"", "doctype": "DocField", @@ -878,9 +866,7 @@ "cancel": 1, "create": 1, "doctype": "DocPerm", - "report": 1, "role": "Material Master Manager", - "submit": 0, "write": 1 }, { @@ -888,9 +874,7 @@ "cancel": 0, "create": 0, "doctype": "DocPerm", - "report": 1, "role": "Material Manager", - "submit": 0, "write": 0 }, { @@ -898,21 +882,7 @@ "cancel": 0, "create": 0, "doctype": "DocPerm", - "report": 1, "role": "Material User", - "submit": 0, "write": 0 - }, - { - "doctype": "DocPerm", - "role": "Sales User" - }, - { - "doctype": "DocPerm", - "role": "Purchase User" - }, - { - "doctype": "DocPerm", - "role": "Accounts User" } ] \ No newline at end of file diff --git a/stock/doctype/item/test_item.py b/stock/doctype/item/test_item.py index b9b67e2db1f..7be6ea56edc 100644 --- a/stock/doctype/item/test_item.py +++ b/stock/doctype/item/test_item.py @@ -44,7 +44,6 @@ test_records = [ "is_purchase_item": "Yes", "is_sales_item": "Yes", "is_service_item": "No", - "is_sample_item": "No", "inspection_required": "No", "is_pro_applicable": "No", "is_sub_contracted_item": "No", @@ -82,7 +81,6 @@ test_records = [ "is_purchase_item": "Yes", "is_sales_item": "Yes", "is_service_item": "No", - "is_sample_item": "No", "inspection_required": "No", "is_pro_applicable": "No", "is_sub_contracted_item": "No", @@ -108,7 +106,6 @@ test_records = [ "is_purchase_item": "Yes", "is_sales_item": "Yes", "is_service_item": "No", - "is_sample_item": "No", "inspection_required": "No", "is_pro_applicable": "No", "is_sub_contracted_item": "No", @@ -128,7 +125,6 @@ test_records = [ "is_purchase_item": "Yes", "is_sales_item": "Yes", "is_service_item": "No", - "is_sample_item": "No", "inspection_required": "No", "is_pro_applicable": "No", "is_sub_contracted_item": "No", @@ -149,7 +145,6 @@ test_records = [ "is_purchase_item": "Yes", "is_sales_item": "Yes", "is_service_item": "No", - "is_sample_item": "No", "inspection_required": "No", "is_pro_applicable": "Yes", "is_sub_contracted_item": "Yes", @@ -168,7 +163,6 @@ test_records = [ "is_purchase_item": "Yes", "is_sales_item": "Yes", "is_service_item": "No", - "is_sample_item": "No", "inspection_required": "No", "is_pro_applicable": "No", "is_sub_contracted_item": "No", @@ -188,7 +182,6 @@ test_records = [ "is_purchase_item": "Yes", "is_sales_item": "Yes", "is_service_item": "No", - "is_sample_item": "No", "inspection_required": "No", "is_pro_applicable": "No", "is_sub_contracted_item": "No", @@ -209,7 +202,6 @@ test_records = [ "is_purchase_item": "Yes", "is_sales_item": "Yes", "is_service_item": "No", - "is_sample_item": "No", "inspection_required": "No", "is_pro_applicable": "No", "is_sub_contracted_item": "No", diff --git a/stock/doctype/stock_entry/test_stock_entry.py b/stock/doctype/stock_entry/test_stock_entry.py index cee231e62fc..5c7ce21b03e 100644 --- a/stock/doctype/stock_entry/test_stock_entry.py +++ b/stock/doctype/stock_entry/test_stock_entry.py @@ -42,11 +42,42 @@ 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") + from stock.doctype.stock_ledger_entry.stock_ledger_entry import InvalidWarehouseCompany st1 = webnotes.bean(copy=test_records[0]) st1.doclist[1].t_warehouse="_Test Warehouse 2 - _TC1" st1.insert() self.assertRaises(InvalidWarehouseCompany, st1.submit) + + webnotes.session.user = "Administrator" + + 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") + + st1 = webnotes.bean(copy=test_records[0]) + st1.doc.company = "_Test Company 1" + st1.doclist[1].t_warehouse="_Test Warehouse 2 - _TC1" + st1.insert() + self.assertRaises(UserNotAllowedForWarehouse, st1.submit) + + webnotes.session.user = "test2@example.com" + st1 = webnotes.bean(copy=test_records[0]) + st1.doc.company = "_Test Company 1" + st1.doclist[1].t_warehouse="_Test Warehouse 2 - _TC1" + st1.insert() + st1.submit() + + webnotes.session.user = "Administrator" def test_material_receipt_gl_entry(self): self._clear_stock_account_balance() diff --git a/stock/doctype/stock_ledger_entry/stock_ledger_entry.py b/stock/doctype/stock_ledger_entry/stock_ledger_entry.py index 748cf693bf4..3b10ae4278e 100644 --- a/stock/doctype/stock_ledger_entry/stock_ledger_entry.py +++ b/stock/doctype/stock_ledger_entry/stock_ledger_entry.py @@ -25,12 +25,14 @@ class DocType(DocListController): self.doclist = doclist def validate(self): + from stock.utils import validate_warehouse_user 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() - self.validate_warehouse_user() + validate_warehouse_user(self.doc.warehouse) self.validate_warehouse_company() self.actual_amt_check() self.check_stock_frozen_date() @@ -55,16 +57,6 @@ class DocType(DocListController): self.doc.fields.pop('batch_bal') - def validate_warehouse_user(self): - if webnotes.session.user=="Administrator": - return - warehouse_users = [p[0] for p in webnotes.conn.sql("""select user from `tabWarehouse User` - where parent=%s""", self.doc.warehouse)] - - if warehouse_users and not webnotes.session.user in warehouse_users: - webnotes.msgprint(_("User not allowed entry in the Warehouse") \ - + ": " + webnotes.session.user + " / " + self.doc.warehouse, raise_exception = 1) - 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: diff --git a/stock/doctype/stock_reconciliation/stock_reconciliation.py b/stock/doctype/stock_reconciliation/stock_reconciliation.py index f36daad2584..324d589f297 100644 --- a/stock/doctype/stock_reconciliation/stock_reconciliation.py +++ b/stock/doctype/stock_reconciliation/stock_reconciliation.py @@ -287,8 +287,8 @@ class DocType(StockController): stock_value_difference = {} for d in self.entries: - diff = get_buying_amount(d.item_code, self.doc.doctype, self.doc.name, - d.voucher_detail_no, stock_ledger_entries.get((d.item_code, d.warehouse), [])) + diff = get_buying_amount(self.doc.doctype, self.doc.name, d.voucher_detail_no, + stock_ledger_entries.get((d.item_code, d.warehouse), [])) stock_value_difference.setdefault(d.warehouse, 0.0) stock_value_difference[d.warehouse] -= diff diff --git a/stock/doctype/warehouse/test_warehouse.py b/stock/doctype/warehouse/test_warehouse.py index 99094ebaa65..40a8ff21c12 100644 --- a/stock/doctype/warehouse/test_warehouse.py +++ b/stock/doctype/warehouse/test_warehouse.py @@ -17,7 +17,11 @@ test_records = [ [{ "doctype": "Warehouse", "warehouse_name": "_Test Warehouse 2", - "company": "_Test Company 1", - "account": "_Test Account Stock In Hand - _TC1" + "account": "_Test Account Stock In Hand - _TC1", + "company": "_Test Company 1" + }, { + "doctype": "Warehouse User", + "parentfield": "warehouse_users", + "user": "test2@example.com" }] ] diff --git a/stock/report/items_to_be_requested/items_to_be_requested.txt b/stock/report/items_to_be_requested/items_to_be_requested.txt index c149c969409..91e8ca3f269 100644 --- a/stock/report/items_to_be_requested/items_to_be_requested.txt +++ b/stock/report/items_to_be_requested/items_to_be_requested.txt @@ -2,7 +2,7 @@ { "creation": "2013-08-20 15:08:10", "docstatus": 0, - "modified": "2013-08-20 15:10:43", + "modified": "2013-08-20 15:10:45", "modified_by": "Administrator", "owner": "Administrator" }, @@ -10,7 +10,7 @@ "doctype": "Report", "is_standard": "Yes", "name": "__common__", - "query": "SELECT\n tabBin.item_code as \"Item:Link/Item:120\",\n tabBin.warehouse as \"Item:Link/Warehouse:120\",\n tabBin.actual_qty as \"Actual:Float:90\",\n tabBin.indented_qty as \"Requested:Float:90\",\n tabBin.reserved_qty as \"Reserved:Float:90\",\n tabBin.ordered_qty as \"Ordered:Float:90\",\n tabBin.projected_qty as \"Projected:Float:90\"\nFROM\n tabBin, tabItem\nWHERE\n tabBin.item_code = tabItem.name\n AND tabItem.is_purchase_item = \"Yes\"\n AND tabBin.projected_qty < 0\nORDER BY\n tabBin.projected_qty ASC", + "query": "SELECT\n tabBin.item_code as \"Item:Link/Item:120\",\n tabBin.warehouse as \"Warehouse:Link/Warehouse:120\",\n tabBin.actual_qty as \"Actual:Float:90\",\n tabBin.indented_qty as \"Requested:Float:90\",\n tabBin.reserved_qty as \"Reserved:Float:90\",\n tabBin.ordered_qty as \"Ordered:Float:90\",\n tabBin.projected_qty as \"Projected:Float:90\"\nFROM\n tabBin, tabItem\nWHERE\n tabBin.item_code = tabItem.name\n AND tabItem.is_purchase_item = \"Yes\"\n AND tabBin.projected_qty < 0\nORDER BY\n tabBin.projected_qty ASC", "ref_doctype": "Item", "report_name": "Items To Be Requested", "report_type": "Query Report" diff --git a/stock/utils.py b/stock/utils.py index f0e948177b6..17149faca40 100644 --- a/stock/utils.py +++ b/stock/utils.py @@ -8,6 +8,7 @@ from webnotes.utils import flt, cstr, nowdate, add_days, cint from webnotes.defaults import get_global_default from webnotes.utils.email_lib import sendmail +class UserNotAllowedForWarehouse(webnotes.ValidationError): pass def get_stock_balance_on(warehouse_list, posting_date=None): if not posting_date: posting_date = nowdate() @@ -208,20 +209,28 @@ def get_warehouse_list(doctype, txt, searchfield, start, page_len, filters): wlist.append([w]) return wlist -def get_buying_amount(item_code, voucher_type, voucher_no, voucher_detail_no, - stock_ledger_entries, item_sales_bom=None): - if item_sales_bom and item_sales_bom.get(item_code): - # sales bom item - buying_amount = 0.0 - for bom_item in item_sales_bom[item_code]: - if bom_item.get("parent_detail_docname")==voucher_detail_no: - buying_amount += _get_buying_amount(voucher_type, voucher_no, voucher_detail_no, stock_ledger_entries) - return buying_amount - else: - # doesn't have sales bom - return _get_buying_amount(voucher_type, voucher_no, voucher_detail_no, stock_ledger_entries) +def validate_warehouse_user(warehouse): + if webnotes.session.user=="Administrator": + return + warehouse_users = [p[0] for p in webnotes.conn.sql("""select user from `tabWarehouse User` + where parent=%s""", warehouse)] + + if warehouse_users and not (webnotes.session.user in warehouse_users): + webnotes.throw(_("Not allowed entry in Warehouse") \ + + ": " + warehouse, UserNotAllowedForWarehouse) + +def get_sales_bom_buying_amount(item_code, warehouse, voucher_type, voucher_no, voucher_detail_no, + stock_ledger_entries, item_sales_bom): + # sales bom item + buying_amount = 0.0 + for bom_item in item_sales_bom[item_code]: + if bom_item.get("parent_detail_docname")==voucher_detail_no: + buying_amount += get_buying_amount(voucher_type, voucher_no, voucher_detail_no, + stock_ledger_entries.get((bom_item.item_code, warehouse), [])) + + return buying_amount -def _get_buying_amount(voucher_type, voucher_no, item_row, stock_ledger_entries): +def get_buying_amount(voucher_type, voucher_no, item_row, stock_ledger_entries): # IMP NOTE # stock_ledger_entries should already be filtered by item_code and warehouse and # sorted by posting_date desc, posting_time desc diff --git a/support/doctype/support_ticket/support_ticket.txt b/support/doctype/support_ticket/support_ticket.txt index 53d1c7ca41d..dcb45204fd2 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-08-08 14:22:34", + "modified": "2013-08-28 18:29:06", "modified_by": "Administrator", "owner": "Administrator" }, @@ -224,17 +224,6 @@ "oldfieldtype": "Column Break", "read_only": 1 }, - { - "depends_on": "eval:!doc.__islocal", - "doctype": "DocField", - "fieldname": "resolution_details", - "fieldtype": "Small Text", - "label": "Resolution Details", - "no_copy": 1, - "oldfieldname": "resolution_details", - "oldfieldtype": "Text", - "read_only": 1 - }, { "doctype": "DocField", "fieldname": "first_responded_on", @@ -254,6 +243,17 @@ "read_only": 1, "search_index": 0 }, + { + "depends_on": "eval:!doc.__islocal", + "doctype": "DocField", + "fieldname": "resolution_details", + "fieldtype": "Small Text", + "label": "Resolution Details", + "no_copy": 1, + "oldfieldname": "resolution_details", + "oldfieldtype": "Text", + "read_only": 0 + }, { "doctype": "DocField", "fieldname": "content_type", diff --git a/utilities/demo/demo-login.html b/utilities/demo/demo-login.html index ef24678e27a..4595cb7d355 100644 --- a/utilities/demo/demo-login.html +++ b/utilities/demo/demo-login.html @@ -8,7 +8,7 @@

+ class="form-control" placeholder="Your Email Id (optional)">