Merge branch 'temp'
diff --git a/controllers/buying_controller.py b/controllers/buying_controller.py
index cd822e6..0c25b98 100644
--- a/controllers/buying_controller.py
+++ b/controllers/buying_controller.py
@@ -47,13 +47,13 @@
self.set_total_in_words()
def validate_warehouse_belongs_to_company(self):
- for d in self.doclist.get({"warehouse": True}):
- warehouse_company = webnotes.conn.get_value("Warehouse", d.warehouse, "company")
- if warehouse_company and warehouse_company != self.doc.company:
+ 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(_("Warehouse must belong to company") + \
- (": %s (%s, %s)" % (d.warehouse, warehouse_company, self.doc.company)),
+ (": %s (%s, %s)" % (warehouse, company, self.doc.company)),
raise_exception=WrongWarehouseCompany)
-
+
def validate_stock_or_nonstock_items(self):
items = [d.item_code for d in self.doclist.get({"parentfield": self.fname})]
if self.stock_items:
diff --git a/home/page/latest_updates/latest_updates.js b/home/page/latest_updates/latest_updates.js
index b768f1a..e11b9c9 100644
--- a/home/page/latest_updates/latest_updates.js
+++ b/home/page/latest_updates/latest_updates.js
@@ -1,4 +1,6 @@
erpnext.updates = [
+ ["2nd May", ["Buying: Warehouse must belong to same company as transaction",
+ "Price List": "Added Currency Field. One price list can have only one currency"]],
["18th April", ["Cost Center: Set a default Cost Center for a Company"]],
["12th April", ["Employee: List of Leave Approvers who can approve the Employee's Leave Applications"]],
["10th April", ["Redesigned File Uploads and added File Manager in Setup"]],
diff --git a/setup/doctype/backup_manager/backup_googledrive.py b/setup/doctype/backup_manager/backup_googledrive.py
index a705f0e..533b37d 100644
--- a/setup/doctype/backup_manager/backup_googledrive.py
+++ b/setup/doctype/backup_manager/backup_googledrive.py
@@ -92,8 +92,7 @@
mimetype = mimetypes.types_map.get("." + ext) or "application/octet-stream"
#Compare Local File with Server File
- param = {}
- children = drive_service.children().list(folderId=files_folder_id, **param).execute()
+ children = drive_service.children().list(folderId=files_folder_id).execute()
for child in children.get('items', []):
file = drive_service.files().get(fileId=child['id']).execute()
if filename == file['title'] and size == int(file['fileSize']):
diff --git a/setup/doctype/backup_manager/backup_manager.js b/setup/doctype/backup_manager/backup_manager.js
index 8d2d8de..c78be3a 100644
--- a/setup/doctype/backup_manager/backup_manager.js
+++ b/setup/doctype/backup_manager/backup_manager.js
@@ -1,67 +1,90 @@
-cur_frm.cscript.refresh = function(doc) {
- cur_frm.disable_save();
-}
-
-//dropbox
-cur_frm.cscript.allow_dropbox_access = function(doc) {
- if (doc.send_notifications_to == '') {
- msgprint("Please enter email address.")
- }
- else {
- wn.call({
- method: "setup.doctype.backup_manager.backup_dropbox.get_dropbox_authorize_url",
- callback: function(r) {
- if(!r.exc) {
- cur_frm.set_value("dropbox_access_secret", r.message.secret);
- cur_frm.set_value("dropbox_access_key", r.message.key);
- cur_frm.save(null, function() {
- window.open(r.message.url);
- });
- }
+$.extend(cur_frm.cscript, {
+ refresh: function() {
+ cur_frm.disable_save();
+
+ if(!(cint(cur_frm.doc.dropbox_access_allowed) ||
+ cint(cur_frm.doc.gdrive_access_allowed))) {
+ cur_frm.set_intro(wn._("You can start by selecting backup frequency and \
+ granting access for sync"));
+ } else {
+ var services = {
+ "dropbox": wn._("Dropbox"),
+ "gdrive": wn._("Google Drive")
}
- })
- }
-}
-
-cur_frm.cscript.backup_right_now = function(doc) {
- msgprint("Backing up and uploading. This may take a few minutes.")
- wn.call({
- method: "setup.doctype.backup_manager.backup_manager.take_backups_dropbox",
- callback: function(r) {
- msgprint("Backups taken. Please check your email for the response.")
+ var active_services = [];
+
+ $.each(services, function(service, label) {
+ var access_allowed = cint(cur_frm.doc[service + "_access_allowed"]);
+ var frequency = cur_frm.doc["upload_backups_to_" + service];
+ if(access_allowed && frequency && frequency !== "Never") {
+ active_services.push(label + " [" + frequency + "]");
+ }
+ });
+
+ if(active_services.length > 0) {
+ cur_frm.set_intro(wn._("Backups will be uploaded to") + ": " +
+ wn.utils.comma_and(active_services));
+ } else {
+ cur_frm.set_intro("");
+ }
}
- })
-}
-//gdrive
-cur_frm.cscript.allow_gdrive_access = function(doc) {
- if (doc.send_notifications_to == '') {
- msgprint("Please enter email address.")
- }
- else {
- wn.call({
- method: "setup.doctype.backup_manager.backup_googledrive.get_gdrive_authorize_url",
- callback: function(r) {
- if(!r.exc) {
- window.open(r.message.authorize_url);
+
+ },
+
+ validate_send_notifications_to: function() {
+ if(!cur_frm.doc.send_notifications_to) {
+ msgprint(wn._("Please specify") + ": " +
+ wn._(wn.meta.get_label(cur_frm.doctype, "send_notifications_to")));
+ return false;
+ }
+
+ return true;
+ },
+
+ allow_dropbox_access: function() {
+ if(cur_frm.cscript.validate_send_notifications_to()) {
+ wn.call({
+ method: "setup.doctype.backup_manager.backup_dropbox.get_dropbox_authorize_url",
+ callback: function(r) {
+ if(!r.exc) {
+ cur_frm.set_value("dropbox_access_secret", r.message.secret);
+ cur_frm.set_value("dropbox_access_key", r.message.key);
+ cur_frm.save(null, function() {
+ window.open(r.message.url);
+ });
+ }
}
- }
- })
- }
-}
-
-cur_frm.cscript.validate_gdrive = function(doc) {
- wn.call({
- method: "setup.doctype.backup_manager.backup_googledrive.gdrive_callback",
- args: {
- verification_code: doc.verification_code
- },
- });
-}
-
-cur_frm.cscript.upload_backups_to_dropbox = function(doc) {
- cur_frm.save()
-}
-
-cur_frm.cscript.upload_backups_to_gdrive = function(doc) {
- cur_frm.save()
-}
+ });
+ }
+ },
+
+ allow_gdrive_access: function() {
+ if(cur_frm.cscript.validate_send_notifications_to()) {
+ wn.call({
+ method: "setup.doctype.backup_manager.backup_googledrive.get_gdrive_authorize_url",
+ callback: function(r) {
+ if(!r.exc) {
+ window.open(r.message.authorize_url);
+ }
+ }
+ });
+ }
+ },
+
+ validate_gdrive: function() {
+ wn.call({
+ method: "setup.doctype.backup_manager.backup_googledrive.gdrive_callback",
+ args: {
+ verification_code: cur_frm.doc.verification_code
+ },
+ });
+ },
+
+ upload_backups_to_dropbox: function() {
+ cur_frm.save();
+ },
+
+ upload_backups_to_gdrive: function() {
+ cur_frm.save();
+ },
+});
\ No newline at end of file
diff --git a/setup/doctype/backup_manager/backup_manager.py b/setup/doctype/backup_manager/backup_manager.py
index a8ecd63..c91cf11 100644
--- a/setup/doctype/backup_manager/backup_manager.py
+++ b/setup/doctype/backup_manager/backup_manager.py
@@ -20,8 +20,8 @@
if webnotes.conn.get_value("Backup Manager", None, "upload_backups_to_dropbox")==freq:
take_backups_dropbox()
- if webnotes.conn.get_value("Backup Manager", None, "upload_backups_to_gdrive")==freq:
- take_backups_gdrive()
+ # if webnotes.conn.get_value("Backup Manager", None, "upload_backups_to_gdrive")==freq:
+ # take_backups_gdrive()
@webnotes.whitelist()
def take_backups_dropbox():
@@ -35,7 +35,7 @@
except Exception:
file_and_error = [" - ".join(f) for f in zip(did_not_upload, error_log)]
error_message = ("\n".join(file_and_error) + "\n" + webnotes.getTraceback())
- print error_message
+ webnotes.errprint(error_message)
send_email(False, "Dropbox", error_message)
#backup to gdrive
@@ -51,7 +51,7 @@
except Exception:
file_and_error = [" - ".join(f) for f in zip(did_not_upload, error_log)]
error_message = ("\n".join(file_and_error) + "\n" + webnotes.getTraceback())
- print error_message
+ webnotes.errprint(error_message)
send_email(False, "Google Drive", error_message)
def send_email(success, service_name, error_status=None):
diff --git a/setup/doctype/backup_manager/backup_manager.txt b/setup/doctype/backup_manager/backup_manager.txt
index 9a43f34..2d6f191 100644
--- a/setup/doctype/backup_manager/backup_manager.txt
+++ b/setup/doctype/backup_manager/backup_manager.txt
@@ -1,8 +1,8 @@
[
{
- "creation": "2013-03-15 11:06:59",
+ "creation": "2013-04-30 12:58:38",
"docstatus": 0,
- "modified": "2013-03-15 17:27:33",
+ "modified": "2013-05-02 11:42:08",
"modified_by": "Administrator",
"owner": "Administrator"
},
@@ -109,6 +109,7 @@
"doctype": "DocField",
"fieldname": "sync_with_gdrive",
"fieldtype": "Section Break",
+ "hidden": 1,
"label": "Sync with Google Drive"
},
{
diff --git a/setup/doctype/price_list/price_list.txt b/setup/doctype/price_list/price_list.txt
index a230f5b..bce8aae 100644
--- a/setup/doctype/price_list/price_list.txt
+++ b/setup/doctype/price_list/price_list.txt
@@ -2,7 +2,7 @@
{
"creation": "2013-01-25 11:35:09",
"docstatus": 0,
- "modified": "2013-01-22 14:56:41",
+ "modified": "2013-05-02 14:44:24",
"modified_by": "Administrator",
"owner": "Administrator"
},
@@ -53,12 +53,20 @@
"reqd": 1
},
{
+ "doctype": "DocField",
+ "fieldname": "currency",
+ "fieldtype": "Link",
+ "label": "Currency",
+ "options": "Currency",
+ "reqd": 1
+ },
+ {
"depends_on": "price_list_name",
"doctype": "DocField",
"fieldname": "how_to_upload",
"fieldtype": "HTML",
"label": "How to upload",
- "options": "<div class=\"help\">Use the <a href=\"#data-import-tool\">Data Import Tool</a> to upload, update Item Prices in bulk:\n<ol> \n<li>Go to Data Import Tool.\n<li>Select \"Item\"\n<li>Check on \"With Data\"\n<li>Download \"Item Price\" from Child Tables.\n<li>Update the prices required and add new rows if required.\n<li>Check on \"Overwrite\"\n<li>Upload the modified sheet.\n</div>\n"
+ "options": "<div class=\"well\">Use the <a href=\"#data-import-tool\">Data Import Tool</a> to upload, update Item Prices in bulk:\n<ol> \n<li>Go to Data Import Tool.\n<li>Select \"Item\"\n<li>Check on \"With Data\"\n<li>Download \"Item Price\" from Child Tables.\n<li>Update the prices required and add new rows if required.\n<li>Check on \"Overwrite\"\n<li>Upload the modified sheet.\n</div>\n"
},
{
"cancel": 0,
@@ -78,7 +86,6 @@
"cancel": 1,
"create": 1,
"doctype": "DocPerm",
- "match": "",
"role": "Sales Master Manager",
"write": 1
}
diff --git a/setup/doctype/price_list/test_price_list.py b/setup/doctype/price_list/test_price_list.py
index 53b86a3..30262dc 100644
--- a/setup/doctype/price_list/test_price_list.py
+++ b/setup/doctype/price_list/test_price_list.py
@@ -1,6 +1,7 @@
test_records = [
[{
"doctype": "Price List",
- "price_list_name": "_Test Price List"
+ "price_list_name": "_Test Price List",
+ "currency": "INR"
}]
]
\ No newline at end of file
diff --git a/stock/doctype/item/item.js b/stock/doctype/item/item.js
index 8b3e044..2635f3e 100644
--- a/stock/doctype/item/item.js
+++ b/stock/doctype/item/item.js
@@ -14,6 +14,8 @@
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
+cur_frm.add_fetch("price_list_name", "currency", "ref_currency")
+
cur_frm.cscript.refresh = function(doc) {
// make sensitive fields(has_serial_no, is_stock_item, valuation_method)
// read only if any stock ledger entry exists
diff --git a/stock/doctype/item/item.py b/stock/doctype/item/item.py
index 6b6dfb3..8a804d8 100644
--- a/stock/doctype/item/item.py
+++ b/stock/doctype/item/item.py
@@ -23,6 +23,9 @@
from webnotes import msgprint, _
from webnotes.model.controller import DocListController
+
+class PriceListCurrencyMismatch(Exception): pass
+
class DocType(DocListController):
def validate(self):
if not self.doc.stock_uom:
@@ -33,7 +36,7 @@
self.add_default_uom_in_conversion_factor_table()
self.valiadte_item_type()
self.check_for_active_boms()
- self.check_ref_rate_detail()
+ self.validate_price_lists()
self.fill_customer_code()
self.check_item_tax()
self.validate_barcode()
@@ -121,16 +124,21 @@
if cstr(self.doc.fields.get(d)) != 'Yes':
_check_for_active_boms(fl[d])
- def check_ref_rate_detail(self):
- check_list=[]
+ def validate_price_lists(self):
+ price_lists=[]
for d in getlist(self.doclist,'ref_rate_details'):
- if [cstr(d.price_list_name), cstr(d.ref_currency),
- cint(d.selling), cint(d.buying)] in check_list:
- msgprint("Ref Rate is entered twice for Price List : '%s' and Currency : '%s'." %
- (d.price_list_name,d.ref_currency), raise_exception=1)
+ if d.price_list_name in price_lists:
+ msgprint(_("Cannot have two prices for same Price List") + ": " + d.price_list_name,
+ raise_exception= webnotes.DuplicateEntryError)
else:
- check_list.append([cstr(d.price_list_name),cstr(d.ref_currency)])
-
+ price_list_currency = webnotes.conn.get_value("Price List", d.price_list_name, "currency")
+ if price_list_currency and d.ref_currency != price_list_currency:
+ msgprint(_("Currency does not match Price List Currency for Price List") \
+ + ": " + d.price_list_name, raise_exception=PriceListCurrencyMismatch)
+
+ price_lists.append(d.price_list_name)
+
+
def fill_customer_code(self):
""" Append all the customer codes and insert into "customer_code" field of item table """
cust_code=[]
diff --git a/stock/doctype/item/test_item.py b/stock/doctype/item/test_item.py
index dbbeecc..f5a688c 100644
--- a/stock/doctype/item/test_item.py
+++ b/stock/doctype/item/test_item.py
@@ -20,6 +20,22 @@
test_ignore = ["BOM"]
+class TestItem(unittest.TestCase):
+ def test_duplicate_price_list(self):
+ item = webnotes.bean(copy=test_records[0])
+ item.doc.item_code = "_Test Item 10"
+ item_price = item.doclist.get({"doctype": "Item Price"})[0]
+ item.doclist.append(webnotes.doc(item_price.fields.copy()))
+ self.assertRaises(webnotes.DuplicateEntryError, item.insert)
+
+ def test_price_list_mismatch(self):
+ from stock.doctype.item.item import PriceListCurrencyMismatch
+ item = webnotes.bean(copy=test_records[0])
+ item.doc.item_code = "_Test Item 11"
+ item_price = item.doclist.get({"doctype": "Item Price"})[0].ref_currency="USD"
+ self.assertRaises(PriceListCurrencyMismatch, item.insert)
+
+
test_records = [
[{
"doctype": "Item",
@@ -45,7 +61,14 @@
"warehouse": "_Test Warehouse",
"warehouse_reorder_level": 20,
"warehouse_reorder_qty": 20
- }],
+ }, {
+ "doctype": "Item Price",
+ "parentfield": "ref_rate_details",
+ "price_list_name": "_Test Price List",
+ "ref_rate": 100,
+ "ref_currency": "INR"
+ }
+ ],
[{
"doctype": "Item",
"item_code": "_Test Item Home Desktop 100",