def validate_item(self, item_code, row_num): from erpnext.stock.doctype.item.item import validate_end_of_life, \ validate_is_stock_item, validate_cancelled_item # using try except to catch all validation msgs and display together try: item = frappe.get_doc("Item", item_code) # end of life and stock item validate_end_of_life(item_code, item.end_of_life, item.disabled, verbose=0) validate_is_stock_item(item_code, item.is_stock_item, verbose=0) # item should not be serialized if item.has_serial_no == 1: raise frappe.ValidationError( _("Serialized Item {0} cannot be updated using Stock Reconciliation, please use Stock Entry" ).format(item_code)) # item managed batch-wise not allowed if item.has_batch_no == 1: raise frappe.ValidationError( _("Batched Item {0} cannot be updated using Stock Reconciliation, instead use Stock Entry" ).format(item_code)) # docstatus should be < 2 validate_cancelled_item(item_code, item.docstatus, verbose=0) except Exception as e: self.validation_messages.append( _("Row # ") + ("%d: " % (row_num)) + cstr(e))
def validate_item(self, item_code, row): from erpnext.stock.doctype.item.item import validate_end_of_life, \ validate_is_stock_item, validate_cancelled_item # using try except to catch all validation msgs and display together try: item = frappe.get_doc("Item", item_code) # end of life and stock item validate_end_of_life(item_code, item.end_of_life, item.disabled, verbose=0) validate_is_stock_item(item_code, item.is_stock_item, verbose=0) # item should not be serialized if item.has_serial_no and not row.serial_no and not item.serial_no_series: raise frappe.ValidationError( _("Serial no(s) required for serialized item {0}").format( item_code)) # item managed batch-wise not allowed if item.has_batch_no and not row.batch_no and not item.create_new_batch: raise frappe.ValidationError( _("Batch no is required for batched item {0}").format( item_code)) # docstatus should be < 2 validate_cancelled_item(item_code, item.docstatus, verbose=0) except Exception as e: self.validation_messages.append( _("Row # ") + ("%d: " % (row.idx)) + cstr(e))
def get_access_token(self): if not self.refresh_token: raise frappe.ValidationError(_("GCalendar is not configured.")) data = { 'client_id': self.client_id, 'client_secret': self.get_password(fieldname='client_secret', raise_exception=False), 'refresh_token': self.get_password(fieldname='refresh_token', raise_exception=False), 'grant_type': "refresh_token", 'scope': SCOPES } try: r = requests.post('https://www.googleapis.com/oauth2/v4/token', data=data).json() except requests.exceptions.HTTPError: frappe.throw( _("Something went wrong during the token generation. Please request again an authorization code." )) return r.get('access_token')
def check_docstatus_transition(self, docstatus): """Ensures valid `docstatus` transition. Valid transitions are (number in brackets is `docstatus`): - Save (0) > Save (0) - Save (0) > Submit (1) - Submit (1) > Submit (1) - Submit (1) > Cancel (2) """ if not self.docstatus: self.docstatus = 0 if docstatus==0: if self.docstatus==0: self._action = "save" elif self.docstatus==1: self._action = "submit" self.check_permission("submit") else: raise frappe.DocstatusTransitionError(_("Cannot change docstatus from 0 to 2")) elif docstatus==1: if self.docstatus==1: self._action = "update_after_submit" self.check_permission("submit") elif self.docstatus==2: self._action = "cancel" self.check_permission("cancel") else: raise frappe.DocstatusTransitionError(_("Cannot change docstatus from 1 to 0")) elif docstatus==2: raise frappe.ValidationError(_("Cannot edit cancelled document"))
def get_context(context): enterprise = frappe.form_dict.enterprise if frappe.form_dict.user: add_user(frappe.form_dict.user, enterprise) user = frappe.session.user if not enterprise: raise frappe.ValidationError(_("You need specified IOT Enterprise")) user_roles = frappe.get_roles(frappe.session.user) if 'IOT User' not in user_roles or frappe.session.user == 'Guest': raise frappe.PermissionError("Your account is not an IOT User!") if not (is_enterprise_admin(user, enterprise) or 'IOT Manager' in user_roles): raise frappe.PermissionError context.no_cache = 1 context.show_sidebar = True possible_users = list_possible_users(enterprise) context.parents = [{ "label": enterprise, "route": "/iot_enterprises/" + enterprise }] context.doc = {"enterprise": enterprise, "possible_users": possible_users}
def get_context(context): company = frappe.form_dict.company if frappe.form_dict.user: add_employee(frappe.form_dict.user, company) frappe.local.flags.redirect_location = "/cloud_add_user?company=" + company raise frappe.Redirect user = frappe.session.user if not company: raise frappe.ValidationError(_("You need specified Cloud Enterprise")) user_roles = frappe.get_roles(frappe.session.user) if 'Company Admin' not in user_roles or frappe.session.user == 'Guest': raise frappe.PermissionError("Your account is not an Cloud User!") if not (is_company_admin(user, company) or 'Company Admin' in user_roles): raise frappe.PermissionError context.no_cache = 1 context.show_sidebar = True possible_users = list_possible_users(company) context.parents = [{ "title": company, "route": "/cloud_companies/" + company }] context.doc = {"company": company, "possible_users": possible_users}
def get_token(user, pwd, expires_in=3600, expire_on=None, device=None): """ Get the JWT Token :param user: The user in ctx :param pwd: Pwd to auth :param expires_in: number of seconds till expiry :param expire_on: yyyy-mm-dd HH:mm:ss to specify the expiry (deprecated) :param device: The device in ctx """ if not frappe.db.exists("User", user): raise frappe.ValidationError(_("Invalide User")) from frappe.sessions import clear_sessions login = LoginManager() login.check_if_enabled(user) if not check_password(user, pwd): login.fail('Incorrect password', user=user) login.login_as(user) login.resume = False login.run_trigger('on_session_creation') _expires_in = 3600 if cint(expires_in): _expires_in = cint(expires_in) elif expire_on: _expires_in = (get_datetime(expire_on) - get_datetime()).total_seconds() token = get_bearer_token(user=user, expires_in=_expires_in) frappe.local.response["token"] = token["access_token"] frappe.local.response.update(token)
def get_access_token(self): import requests google_settings = frappe.get_doc("Google Settings") if not google_settings.enable: frappe.throw(_("Google Integration is disabled.")) if not self.indexing_refresh_token: button_label = frappe.bold(_("Allow API Indexing Access")) raise frappe.ValidationError(_("Click on {0} to generate Refresh Token.").format(button_label)) data = { "client_id": google_settings.client_id, "client_secret": google_settings.get_password(fieldname="client_secret", raise_exception=False), "refresh_token": self.get_password(fieldname="indexing_refresh_token", raise_exception=False), "grant_type": "refresh_token", "scope": INDEXING_SCOPES } try: res = requests.post(get_auth_url(), data=data).json() except requests.exceptions.HTTPError: button_label = frappe.bold(_("Allow Google Indexing Access")) frappe.throw(_("Something went wrong during the token generation. Click on {0} to generate a new one.").format(button_label)) return res.get("access_token")
def before_insert(self): if frappe.db.count("Translated Message", { "source": self.source, "language": self.language }): raise frappe.ValidationError( "Translated Message for this source message already exists")
def get_access_token(self): google_settings = self.validate() if not self.refresh_token: button_label = frappe.bold(_("Allow Google Calendar Access")) raise frappe.ValidationError( _("Click on {0} to generate Refresh Token.").format( button_label)) data = { "client_id": google_settings.client_id, "client_secret": google_settings.get_password(fieldname="client_secret", raise_exception=False), "refresh_token": self.get_password(fieldname="refresh_token", raise_exception=False), "grant_type": "refresh_token", "scope": SCOPES } try: r = requests.post(get_auth_url(), data=data).json() except requests.exceptions.HTTPError: button_label = frappe.bold(_("Allow Google Calendar Access")) frappe.throw( _("Something went wrong during the token generation. Click on {0} to generate a new one." ).format(button_label)) return r.get("access_token")
def validate_address(self, address): for field, label in {"country":"Country", "country_code":"Country Code", "pincode":"Pin Code", \ "phone":"Phone", "email_id":"Email ID", "city":"City", "address_line1":"Address Lines"}.items(): if not address.get(field): raise frappe.ValidationError( "Please specify {1} in Address {0}".format( address.get("name"), label))
def check_docstatus_transition(self, docstatus): """Ensures valid `docstatus` transition. Valid transitions are (number in brackets is `docstatus`): - Save (0) > Save (0) - Save (0) > Submit (1) - Submit (1) > Submit (1) - Submit (1) > Cancel (2) """ if not self.docstatus: self.docstatus = 0 if docstatus==0: if self.docstatus==0: self._action = "save" elif self.docstatus==1: self._action = "submit" self.check_permission("submit") else: raise frappe.DocstatusTransitionError(_("Draft Document cannot be cancelled. Please {0} the selected document before cancelling it.").format(frappe.bold(_("Submit")))) elif docstatus==1: if self.docstatus==1: self._action = "update_after_submit" self.check_permission("submit") elif self.docstatus==2: self._action = "cancel" self.check_permission("cancel") else: raise frappe.DocstatusTransitionError(_("Cannot change Document Status from Submitted to Draft.")) elif docstatus==2: raise frappe.ValidationError(_("Cancelled Document cannot be edited."))
def validate_data(self): def _get_msg(row_num, msg): return _("Row # {0}: ").format(row_num+1) + msg self.validation_messages = [] item_warehouse_combinations = [] default_currency = frappe.db.get_default("currency") for row_num, row in enumerate(self.items): # find duplicates if [row.item_code, row.warehouse] in item_warehouse_combinations: self.validation_messages.append(_get_msg(row_num, _("Duplicate entry"))) else: item_warehouse_combinations.append([row.item_code, row.warehouse]) self.validate_item(row.item_code, row_num+1) # validate warehouse if not frappe.db.get_value("Warehouse", row.warehouse): self.validation_messages.append(_get_msg(row_num, _("Warehouse not found in the system"))) # if both not specified if row.qty in ["", None] and row.valuation_rate in ["", None]: self.validation_messages.append(_get_msg(row_num, _("Please specify either Quantity or Valuation Rate or both"))) # do not allow negative quantity if flt(row.qty) < 0: self.validation_messages.append(_get_msg(row_num, _("Negative Quantity is not allowed"))) # do not allow negative valuation if flt(row.valuation_rate) < 0: self.validation_messages.append(_get_msg(row_num, _("Negative Valuation Rate is not allowed"))) if row.qty and not row.valuation_rate: row.valuation_rate = get_stock_balance(row.item_code, row.warehouse, self.posting_date, self.posting_time, with_valuation_rate=True)[1] if not row.valuation_rate: # try if there is a buying price list in default currency buying_rate = frappe.db.get_value("Item Price", {"item_code": row.item_code, "buying": 1, "currency": default_currency}, "price_list_rate") if buying_rate: row.valuation_rate = buying_rate else: # get valuation rate from Item row.valuation_rate = frappe.get_value('Item', row.item_code, 'valuation_rate') # throw all validation messages if self.validation_messages: for msg in self.validation_messages: msgprint(msg) raise frappe.ValidationError(self.validation_messages)
def get_next_mapping_name(self): mappings = [m for m in self.get_plan().mappings if m.enabled] if not self.current_mapping: # first return mappings[0].mapping for i, d in enumerate(mappings): if i == len(mappings) - 1: # last return None if d.mapping == self.current_mapping: return mappings[i + 1].mapping raise frappe.ValidationError('Mapping Broken')
def update(message, source, translated, language): if message: message = frappe.get_doc("Translated Message", message) message.translated = translated message.save(ignore_permissions=1) elif source: message = frappe.new_doc("Translated Message") message.translated = translated message.language = language message.source = source message.save(ignore_permissions=1) else: raise frappe.ValidationError("Message not found")
def is_valid_from_to_dates(self): if self.from_date and self.to_date: from_date = dt.strptime(self.from_date, "%Y-%m-%d") to_date = dt.strptime(self.to_date, "%Y-%m-%d") date_diff = to_date - from_date if (from_date.strftime("%a") == "Fri") and (to_date.strftime("%a") == "Thu") and (date_diff.days == 6): return True else: raise frappe.ValidationError("Invalid From Date and To Date") else: raise frappe.MandatoryError( "From Date and To Date fields are mandatory")
def get_token(user, pwd, expire_on=None, device=None): if not frappe.db.exists("User", user): raise frappe.ValidationError(_("Invalide User")) from frappe.sessions import clear_sessions login = LoginManager() login.check_if_enabled(user) if not check_password(user, pwd): login.fail('Incorrect password', user=user) login.login_as(user) login.resume = False login.run_trigger('on_session_creation') clear_sessions(user, True, device) if expire_on: frappe.flags.jwt_expire_on = expire_on
def reset_pin(): pwd, apwd = None, None if frappe.session.user != "Guest": pwd = frappe.form_dict.get('pwd') apwd = frappe.form_dict.get('apwd') if pwd and apwd: set_encrypted_password("User", frappe.session.user, pwd, fieldname="pin") frappe.db.commit() return "SUCCESS" else: raise frappe.ValidationError( "Passwords does not match or key is missing")
def _get_access(sitemap_page, profile): lft, rgt, public_read, public_write, page_or_generator = frappe.db.get_value( "Website Route", sitemap_page, ["lft", "rgt", "public_read", "public_write", "page_or_generator"]) read = write = admin = private_read = 0 if page_or_generator == "Generator": if not (lft and rgt): raise frappe.ValidationError("Please rebuild Website Route Tree") if profile == "Guest": return {"read": public_read, "write": 0, "admin": 0} if public_write: read = write = 1 elif public_read: read = 1 for perm in frappe.db.sql( """select wsp.`read`, wsp.`write`, wsp.`admin`, ws.lft, ws.rgt, ws.name from `tabWebsite Route Permission` wsp, `tabWebsite Route` ws where wsp.profile = %s and wsp.website_route = ws.name order by lft asc""", (profile, ), as_dict=True): if perm.lft <= lft and perm.rgt >= rgt: if not (public_read or private_read): private_read = perm.read if not read: read = perm.read if not write: write = perm.write if not admin: admin = perm.admin if write: read = write if read and write and admin: break else: read = write = admin = private_read = 1 return { "read": read, "write": write, "admin": admin, "private_read": private_read }
def get_access_token(): if not refresh_token: raise frappe.ValidationError(_("GCalendar is not configured.")) data = { 'client_id': client_id, 'client_secret': client_secret, 'refresh_token': refresh_token, 'grant_type': "refresh_token", 'scope': SCOPES } try: r = requests.post('https://www.googleapis.com/oauth2/v4/token', data=data).json() except requests.exceptions.HTTPError: frappe.throw(_("Something went wrong during the token generation. Please request again an authorization code.")) if r.get('access_token'): frappe.db.set_value("Booking Settings", None, "access_token", cstr(r.get('access_token'))) frappe.db.commit() return r.get('access_token')
def reset_password(): pwd = frappe.form_dict.get('pwd') apwd = frappe.form_dict.get('apwd') key = frappe.form_dict.get('key') if pwd and key and pwd == apwd: res = _get_user_for_update_password(key, None) if res.get('message'): frappe.local.response.http_status_code = 410 return res['message'] else: user = res['user'] _update_password(user, pwd, logout_all_sessions=1) return "SUCCESS" else: raise frappe.ValidationError( "Passwords does not match or key is missing")
def get_token(user, pwd, expire_on=None, device=None): """ Get the JWT Token :param user: The user in ctx :param pwd: Pwd to auth :param expire_on: yyyy-mm-dd HH:mm:ss to specify the expiry :param device: The device in ctx """ if not frappe.db.exists("User", user): raise frappe.ValidationError(_("Invalide User")) from frappe.sessions import clear_sessions login = LoginManager() login.check_if_enabled(user) if not check_password(user, pwd): login.fail('Incorrect password', user=user) login.login_as(user) login.resume = False login.run_trigger('on_session_creation') clear_sessions(user, True, device) if expire_on: frappe.flags.jwt_expire_on = expire_on
def set_shipper_info(self, shipper_id, shipment): shipper_details = frappe.db.get_value("Address", shipper_id, "*", as_dict=True) self.validate_address(shipper_details) tin_no = frappe.db.get_value("Company", shipper_details.get("company"), "tin_no") shipment.RequestedShipment.Shipper.AccountNumber = self.config_obj.account_number shipment.RequestedShipment.Shipper.Contact.PersonName = shipper_details.get( "address_title") shipment.RequestedShipment.Shipper.Contact.CompanyName = shipper_details.get( "company") shipment.RequestedShipment.Shipper.Contact.PhoneNumber = shipper_details.get( "phone") shipment.RequestedShipment.Shipper.Address.StreetLines = [shipper_details.get("address_line1"),\ shipper_details.get("address_line2")] shipment.RequestedShipment.Shipper.Address.City = shipper_details.get( "city") shipment.RequestedShipment.Shipper.Address.StateOrProvinceCode = shipper_details.get( "state_code") shipment.RequestedShipment.Shipper.Address.PostalCode = shipper_details.get( "pincode") shipment.RequestedShipment.Shipper.Address.CountryCode = shipper_details.get( "country_code") shipment.RequestedShipment.Shipper.Address.Residential = True if shipper_details.get("is_residential_address") \ else False if not tin_no: raise frappe.ValidationError( "Please set TIN no in company {0}".format( shipper_details.get("company"))) tin_details = shipment.create_wsdl_object_of_type( 'TaxpayerIdentification') tin_details.TinType.value = "BUSINESS_NATIONAL" tin_details.Number = tin_no shipment.RequestedShipment.Shipper.Tins = [tin_details] return shipper_details
def get_payment_url(self, **kwargs): snap = midtransclient.Snap(is_production=bool(self.is_production), server_key=self.server_key, client_key=self.client_key) param = {} param.update({ "transaction_details": { "order_id": kwargs['reference_docname'], "gross_amount": kwargs['amount'] }, "credit_card": { "secure": True } }) try: trans = snap.create_transaction(param) payment_url = trans['redirect_url'] doc = frappe.get_doc("Midtrans Settings") md5 = hashlib.md5() md5.update( ("{}-{}".format(doc.merchant_id, kwargs['reference_docname']).encode("utf8"))) token = md5.hexdigest() # kwargs.update({ # "token": token # }) create_request_log(kwargs, "Remote", "Midtrans", token) print("Payment url : {}".format(payment_url)) frappe.msgprint("Payment url : {}".format(payment_url)) return payment_url except Exception as e: # frappe.msgprint(_(str(e)), raise_exception=1, indicator='red') raise frappe.ValidationError(str(e))
def __init__(self): super(JSInterpreter, self).__init__() # load javascript path for app in frappe.get_installed_apps(): for hook in frappe.get_hooks('studio_library_path', app_name=app): self.loader.register_path(frappe.get_app_path(app, hook)) # load functions _gbl = tree() replacements = {} for attr in frappe.get_hooks('studio_functions', []): paths = [] if isinstance(attr, dict): for key, value in attr.items(): attr, expand = get_attr(value) if not expand: paths.append(key) self.export_function(key, attr) else: base_path = key for fn, item in inspect.getmembers( attr, is_module_function(base_path)): key = '{0}.{1}'.format(base_path, fn) self.export_function(key, item) paths.append(key) elif isinstance(attr, (list, tuple, set)): raise frappe.ValidationError( 'Invalid hook format {}, should be ("list" or "dict") not "{}"' .format(frappe.as_json(list(attr)), type(attr).__name__)) else: obj, expand = get_attr(attr) if not expand: paths.append(attr) self.export_function(attr, obj) else: base_path = attr for fn, item in inspect.getmembers( obj, is_module_function(base_path)): attr = '{0}.{1}'.format(base_path, fn) self.export_function(key, item) paths.append(attr) for path in paths: parts = path.split('.') fn = parts.pop() actual = None for part in parts: actual = (actual or _gbl)[part] actual[fn] = '{{{0}}}'.format(path.replace('.', '_')) replacements[path.replace( '.', '_' )] = '''function() {{ return call_python("{0}", as_list(arguments)); }}'''.format( path) self.evaljs(''' function as_list(a){ var args = []; for(var i = 0; i < a.length; i++){ args.push(a[i]); } return args; } function enable_document_syncronization(){ ctx.enabled_document_syncronization = true; } function disable_document_syncronization(){ ctx.enabled_document_syncronization = false; } function add_child(field, child){ if (!ctx.enabled_document_syncronization) return; var df = frappe.utils.filter_dict(ctx.meta.fields, {'fieldname': field, 'fieldtype': 'Table'}); if (!df) return; df = df[0]; if (!Array.isArray(doc[df.fieldname])) doc[df.fieldname] = []; if (!child.doctype) child.doctype = df.options; if (!child.parenttype) child.parenttype = doc.doctype; if (!child.paerentfield) child.parentfield = df.fieldname; doc[df.fieldname].push(child); } ''') JS_GLOBALS = [] for k in _gbl.keys(): JS_GLOBALS_PART = k + ' = ' + json.dumps(_gbl[k], indent=2) + ';' for rk, v in replacements.items(): if not rk.startswith(k + '_'): continue JS_GLOBALS_PART = JS_GLOBALS_PART.replace('"{' + rk + '}"', v) JS_GLOBALS.append(JS_GLOBALS_PART) #frappe.msgprint('<pre>{0}</pre>'.format('\n'.join(JS_GLOBALS))) self.evaljs('\n'.join(JS_GLOBALS))
def _msgprint(msg, verbose): if verbose: msgprint(msg, raise_exception=True) else: raise frappe.ValidationError(msg)
def validate_data(self): def _get_msg(row_num, msg): return _("Row # {0}: ").format(row_num+1) + msg self.validation_messages = [] item_warehouse_combinations = [] default_currency = frappe.db.get_default("currency") for row_num, row in enumerate(self.items): # find duplicates if [row.item_code, row.warehouse, row.batch_no] in item_warehouse_combinations:#JDLP - 2017-01-30 - batch_no self.validation_messages.append(_get_msg(row_num, _("Duplicate entry"))) else: item_warehouse_combinations.append([row.item_code, row.warehouse, row.batch_no])#JDLP - 2017-01-30 - batch_no self.validate_item(row.item_code, row_num+1) # validate warehouse if not frappe.db.get_value("Warehouse", row.warehouse): self.validation_messages.append(_get_msg(row_num, _("Warehouse not found in the system"))) # if both not specified if row.qty in ["", None] and row.valuation_rate in ["", None]: self.validation_messages.append(_get_msg(row_num, _("Please specify either Quantity or Valuation Rate or both"))) # do not allow negative quantity if flt(row.qty) < 0: self.validation_messages.append(_get_msg(row_num, _("Negative Quantity is not allowed"))) # do not allow negative valuation if flt(row.valuation_rate) < 0: self.validation_messages.append(_get_msg(row_num, _("Negative Valuation Rate is not allowed"))) if row.qty and not row.valuation_rate: row.valuation_rate = get_stock_balance(row.item_code, row.warehouse, self.posting_date, self.posting_time, with_valuation_rate=True)[1] if not row.valuation_rate: # try if there is a buying price list in default currency buying_rate = frappe.db.get_value("Item Price", {"item_code": row.item_code, "buying": 1, "currency": default_currency}, "price_list_rate") if buying_rate: row.valuation_rate = buying_rate #JDLP - 2017-01-30 - batch_no # if batch_no is required and not provided. has_batch_no = frappe.db.get_value("Item", {"item_code": row.item_code}, "has_batch_no") if has_batch_no == 1 and row.batch_no is None: self.validation_messages.append(_get_msg(row_num, _("Batch number is required"))) #raise frappe.ValidationError, _("Item: {0} managed batch-wise, batch number is required").format(item_code) if has_batch_no == 0 and row.batch_no is not None: self.validation_messages.append(_get_msg(row_num, _("Batch number should be empty"))) #raise frappe.ValidationError, _("Item: {0} is not managed batch-wise, batch number should be empty").format(item_code) #JDLP - 2017-01-30 - batch_no # throw all validation messages if self.validation_messages: for msg in self.validation_messages: msgprint(msg) raise frappe.ValidationError(self.validation_messages)