Skip to content

Commit

Permalink
Merge branch 'staging' into production
Browse files Browse the repository at this point in the history
  • Loading branch information
sahil28297 committed Jun 23, 2021
2 parents 7e18720 + aa5a5c3 commit 25774e5
Show file tree
Hide file tree
Showing 25 changed files with 685 additions and 340 deletions.
58 changes: 58 additions & 0 deletions cypress/integration/depends_on.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
context('Depends On', () => {
before(() => {
cy.login();
cy.visit('/desk');
cy.window().its('frappe').then(frappe => {
frappe.call('frappe.tests.ui_test_helpers.create_doctype', {
name: 'Test Depends On',
fields: [
{
"label": "Test Field",
"fieldname": "test_field",
"fieldtype": "Data",
},
{
"label": "Dependant Field",
"fieldname": "dependant_field",
"fieldtype": "Data",
"mandatory_depends_on": "eval:doc.test_field=='Some Value'",
"read_only_depends_on": "eval:doc.test_field=='Some Other Value'",
},
{
"label": "Display Dependant Field",
"fieldname": "display_dependant_field",
"fieldtype": "Data",
'depends_on': "eval:doc.test_field=='Value'"
},
]
});
});
});
it('should set the field as mandatory depending on other fields value', () => {
cy.new_form('Test Depends On');
cy.fill_field('test_field', 'Some Value');
cy.get('button.primary-action').contains('Save').click();
cy.get('.msgprint-dialog .modal-title').contains('Missing Fields').should('be.visible');
cy.get('body').click();
cy.fill_field('test_field', 'Random value');
cy.get('button.primary-action').contains('Save').click();
cy.get('.msgprint-dialog .modal-title').contains('Missing Fields').should('not.be.visible');
});
it('should set the field as read only depending on other fields value', () => {
cy.new_form('Test Depends On');
cy.fill_field('dependant_field', 'Some Value');
cy.fill_field('test_field', 'Some Other Value');
cy.get('body').click();
cy.get('.control-input [data-fieldname="dependant_field"]').should('be.disabled');
cy.fill_field('test_field', 'Random Value');
cy.get('body').click();
cy.get('.control-input [data-fieldname="dependant_field"]').should('not.be.disabled');
});
it('should display the field depending on other fields value', () => {
cy.get('.control-input [data-fieldname="display_dependant_field"]').should('not.be.visible');
cy.get('.control-input [data-fieldname="test_field"]').clear();
cy.fill_field('test_field', 'Value');
cy.get('body').click();
cy.get('.control-input [data-fieldname="display_dependant_field"]').should('be.visible');
});
});
2 changes: 1 addition & 1 deletion frappe/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
sys.setdefaultencoding("utf-8")

__frappe_version__ = '12.8.1'
__version__ = '2.3.0'
__version__ = '2.3.1'
__title__ = "Frappe Framework"

local = Local()
Expand Down
6 changes: 4 additions & 2 deletions frappe/commands/site.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@
@click.option('--db-name', help='Database name')
@click.option('--db-password', help='Database password')
@click.option('--db-type', default='mariadb', type=click.Choice(['mariadb', 'postgres']), help='Optional "postgres" or "mariadb". Default is "mariadb"')
@click.option('--db-host', help='Database Host')
@click.option('--db-port', type=int, help='Database Port')
@click.option('--mariadb-root-username', default='root', help='Root username for MariaDB')
@click.option('--mariadb-root-password', help='Root password for MariaDB')
@click.option('--no-mariadb-socket', is_flag=True, default=False, help='Set MariaDB host to % and use TCP/IP Socket instead of using the UNIX Socket')
Expand Down Expand Up @@ -137,7 +139,7 @@ def restore(context, sql_file_path, mariadb_root_username=None, mariadb_root_pas
_new_site(frappe.conf.db_name, site, mariadb_root_username=mariadb_root_username,
mariadb_root_password=mariadb_root_password, admin_password=admin_password,
verbose=context.verbose, install_apps=install_app, source_sql=decompressed_file_name,
force=True)
force=True, db_type=frappe.conf.db_type)

# Extract public and/or private files to the restored site, if user has given the path
if with_public_files:
Expand Down Expand Up @@ -457,7 +459,7 @@ def _drop_site(site, root_login='root', root_password=None, archived_sites_path=
else:
click.echo("="*80)
click.echo("Error: The operation has stopped because backup of {s}'s database failed.".format(s=site))
click.echo("Reason: {reason}{sep}".format(reason=err[1], sep="\n"))
click.echo("Reason: {reason}{sep}".format(reason=str(err), sep="\n"))
click.echo("Fix the issue and try again.")
click.echo(
"Hint: Use 'bench drop-site {s} --force' to force the removal of {s}".format(sep="\n", tab="\t", s=site)
Expand Down
12 changes: 11 additions & 1 deletion frappe/contacts/doctype/address/address.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
"county",
"state",
"country",
"country_code",
"pincode",
"column_break0",
"email_id",
Expand Down Expand Up @@ -110,6 +111,7 @@
"fieldname": "phone",
"fieldtype": "Data",
"label": "Phone",
"options": "Phone",
"reqd": 1
},
{
Expand Down Expand Up @@ -158,11 +160,19 @@
"fieldname": "ignore_owner_links",
"fieldtype": "Check",
"label": "Ignore Owner Links"
},
{
"fetch_from": "country.code",
"fieldname": "country_code",
"fieldtype": "Data",
"hidden": 1,
"label": "Country Code",
"read_only": 1
}
],
"icon": "fa fa-map-marker",
"idx": 5,
"modified": "2020-12-02 20:42:36.303850",
"modified": "2021-06-15 08:57:55.857908",
"modified_by": "Administrator",
"module": "Contacts",
"name": "Address",
Expand Down
27 changes: 26 additions & 1 deletion frappe/core/doctype/docfield/docfield.json
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,10 @@
"report_hide",
"remember_last_selected_value",
"ignore_xss_filter",
"property_depends_on_section",
"mandatory_depends_on",
"column_break_38",
"read_only_depends_on",
"display",
"in_filter",
"no_copy",
Expand Down Expand Up @@ -421,11 +425,32 @@
"hidden": 1,
"oldfieldname": "oldfieldtype",
"oldfieldtype": "Data"
},
{
"fieldname": "mandatory_depends_on",
"fieldtype": "Code",
"label": "Mandatory Depends On",
"options": "JS"
},
{
"fieldname": "read_only_depends_on",
"fieldtype": "Code",
"label": "Read Only Depends On",
"options": "JS"
},
{
"fieldname": "property_depends_on_section",
"fieldtype": "Section Break",
"label": "Property Depends On"
},
{
"fieldname": "column_break_38",
"fieldtype": "Column Break"
}
],
"idx": 1,
"istable": 1,
"modified": "2021-04-15 23:05:58.400774",
"modified": "2021-06-10 00:00:53.242492",
"modified_by": "Administrator",
"module": "Core",
"name": "DocField",
Expand Down
2 changes: 1 addition & 1 deletion frappe/core/doctype/doctype/doctype.py
Original file line number Diff line number Diff line change
Expand Up @@ -920,7 +920,7 @@ def check_sort_field(meta):

def check_illegal_depends_on_conditions(docfield):
''' assignment operation should not be allowed in the depends on condition.'''
depends_on_fields = ["depends_on", "collapsible_depends_on"]
depends_on_fields = ["depends_on", "collapsible_depends_on", "mandatory_depends_on", "read_only_depends_on"]
for field in depends_on_fields:
depends_on = docfield.get(field, None)
if depends_on and ("=" in depends_on) and \
Expand Down
13 changes: 9 additions & 4 deletions frappe/core/doctype/doctype/test_doctype.py
Original file line number Diff line number Diff line change
Expand Up @@ -96,14 +96,19 @@ def test_depends_on_fields(self):
def test_all_depends_on_fields_conditions(self):
import re

docfields = frappe.get_all("DocField", or_filters={
docfields = frappe.get_all("DocField",
or_filters={
"ifnull(depends_on, '')": ("!=", ''),
"ifnull(collapsible_depends_on, '')": ("!=", '')
}, fields=["parent", "depends_on", "collapsible_depends_on", "fieldname", "fieldtype"])
"ifnull(collapsible_depends_on, '')": ("!=", ''),
"ifnull(mandatory_depends_on, '')": ("!=", ''),
"ifnull(read_only_depends_on, '')": ("!=", '')
},
fields=["parent", "depends_on", "collapsible_depends_on", "mandatory_depends_on",
"read_only_depends_on", "fieldname", "fieldtype"])

pattern = """[\w\.:_]+\s*={1}\s*[\w\.@'"]+"""
for field in docfields:
for depends_on in ["depends_on", "collapsible_depends_on"]:
for depends_on in ["depends_on", "collapsible_depends_on", "mandatory_depends_on", "read_only_depends_on"]:
condition = field.get(depends_on)
if condition:
self.assertFalse(re.match(pattern, condition))
Expand Down
25 changes: 20 additions & 5 deletions frappe/custom/doctype/custom_field/custom_field.json
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
{
"actions": [],
"allow_import": 1,
"creation": "2013-01-10 16:34:01",
"description": "Adds a custom field to a DocType",
Expand All @@ -24,10 +25,8 @@
"collapsible_depends_on",
"default",
"depends_on",
"description",
"permlevel",
"width",
"columns",
"mandatory_depends_on",
"read_only_depends_on",
"properties",
"reqd",
"unique",
Expand All @@ -47,7 +46,11 @@
"search_index",
"allow_in_quick_entry",
"ignore_xss_filter",
"translatable"
"translatable",
"description",
"permlevel",
"width",
"columns"
],
"fields": [
{
Expand Down Expand Up @@ -356,6 +359,18 @@
"fieldname": "allow_in_quick_entry",
"fieldtype": "Check",
"label": "Allow in Quick Entry"
},
{
"fieldname": "mandatory_depends_on",
"fieldtype": "Code",
"label": "Mandatory Depends On",
"length": 255
},
{
"fieldname": "read_only_depends_on",
"fieldtype": "Code",
"label": "Read Only Depends On",
"length": 255
}
],
"icon": "fa fa-glass",
Expand Down
2 changes: 2 additions & 0 deletions frappe/custom/doctype/customize_form/customize_form.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,8 @@
'report_hide': 'Check',
'allow_on_submit': 'Check',
'translatable': 'Check',
'mandatory_depends_on': 'Data',
'read_only_depends_on': 'Data',
'depends_on': 'Data',
'description': 'Text',
'default': 'Text',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,10 @@
"allow_on_submit",
"report_hide",
"remember_last_selected_value",
"property_depends_on_section",
"mandatory_depends_on",
"column_break_33",
"read_only_depends_on",
"display",
"default",
"in_filter",
Expand Down Expand Up @@ -354,6 +358,27 @@
"fieldname": "allow_in_quick_entry",
"fieldtype": "Check",
"label": " Allow in Quick Entry "
},
{
"fieldname": "property_depends_on_section",
"fieldtype": "Section Break",
"label": "Property Depends On"
},
{
"fieldname": "mandatory_depends_on",
"fieldtype": "Code",
"label": "Mandatory Depends On",
"options": "JS"
},
{
"fieldname": "column_break_33",
"fieldtype": "Column Break"
},
{
"fieldname": "read_only_depends_on",
"fieldtype": "Code",
"label": "Read Only Depends On",
"options": "JS"
}
],
"idx": 1,
Expand Down
2 changes: 2 additions & 0 deletions frappe/database/mariadb/framework_mariadb.sql
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@ CREATE TABLE `tabDocField` (
`show_preview_popup` int(1) NOT NULL DEFAULT 0,
`trigger` varchar(255) DEFAULT NULL,
`collapsible_depends_on` text,
`mandatory_depends_on` text,
`read_only_depends_on` text,
`depends_on` text,
`permlevel` int(11) NOT NULL DEFAULT 0,
`ignore_user_permissions` int(1) NOT NULL DEFAULT 0,
Expand Down
2 changes: 2 additions & 0 deletions frappe/database/postgres/framework_postgres.sql
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@ CREATE TABLE "tabDocField" (
"show_preview_popup" smallint NOT NULL DEFAULT 0,
"trigger" varchar(255) DEFAULT NULL,
"collapsible_depends_on" text,
"mandatory_depends_on" text,
"read_only_depends_on" text,
"depends_on" text,
"permlevel" bigint NOT NULL DEFAULT 0,
"ignore_user_permissions" smallint NOT NULL DEFAULT 0,
Expand Down
10 changes: 6 additions & 4 deletions frappe/database/postgres/setup_db.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import frappe, subprocess, os
from six.moves import input

def setup_database(force, source_sql, verbose):
def setup_database(force, source_sql=None, verbose=False):
root_conn = get_root_connection()
root_conn.commit()
root_conn.sql("DROP DATABASE IF EXISTS `{0}`".format(frappe.conf.db_name))
Expand All @@ -16,10 +16,12 @@ def setup_database(force, source_sql, verbose):
subprocess_env = os.environ.copy()
subprocess_env['PGPASSWORD'] = str(frappe.conf.db_password)
# bootstrap db
if not source_sql:
source_sql = os.path.join(os.path.dirname(__file__), 'framework_postgres.sql')

subprocess.check_output([
'psql', frappe.conf.db_name, '-h', frappe.conf.db_host or 'localhost', '-U',
frappe.conf.db_name, '-f',
os.path.join(os.path.dirname(__file__), 'framework_postgres.sql')
frappe.conf.db_name, '-f', source_sql
], env=subprocess_env)

frappe.connect()
Expand Down Expand Up @@ -49,4 +51,4 @@ def get_root_connection(root_login=None, root_password=None):

frappe.local.flags.root_connection = frappe.database.get_db(user=root_login, password=root_password)

return frappe.local.flags.root_connection
return frappe.local.flags.root_connection
15 changes: 11 additions & 4 deletions frappe/installer.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,8 @@ def install_db(root_login="root", root_password=None, db_name=None, source_sql=N
if not db_type:
db_type = frappe.conf.db_type or 'mariadb'

make_conf(db_name, site_config=site_config, db_password=db_password, db_type=db_type)
make_conf(db_name, site_config=site_config, db_password=db_password, db_type=db_type,
db_host=db_host, db_port=db_port)
frappe.flags.in_install_db = True

frappe.flags.root_login = root_login
Expand Down Expand Up @@ -190,14 +191,14 @@ def init_singles():
doc.flags.ignore_validate=True
doc.save()

def make_conf(db_name=None, db_password=None, site_config=None, db_type=None):
def make_conf(db_name=None, db_password=None, site_config=None, db_type=None, db_host=None, db_port=None):
site = frappe.local.site
make_site_config(db_name, db_password, site_config, db_type=db_type)
make_site_config(db_name, db_password, site_config, db_type=db_type, db_host=db_host, db_port=db_port)
sites_path = frappe.local.sites_path
frappe.destroy()
frappe.init(site, sites_path=sites_path)

def make_site_config(db_name=None, db_password=None, site_config=None, db_type=None):
def make_site_config(db_name=None, db_password=None, site_config=None, db_type=None, db_host=None, db_port=None):
frappe.create_folder(os.path.join(frappe.local.site_path))
site_file = get_site_config_path()

Expand All @@ -208,6 +209,12 @@ def make_site_config(db_name=None, db_password=None, site_config=None, db_type=N
if db_type:
site_config['db_type'] = db_type

if db_host:
site_config['db_host'] = db_host

if db_port:
site_config['db_port'] = db_port

with open(site_file, "w") as f:
f.write(json.dumps(site_config, indent=1, sort_keys=True))

Expand Down
Loading

0 comments on commit 25774e5

Please sign in to comment.