diff --git a/erpnext/accounts/doctype/bank_account/bank_account.py b/erpnext/accounts/doctype/bank_account/bank_account.py index aced4258526..30dbb013be8 100644 --- a/erpnext/accounts/doctype/bank_account/bank_account.py +++ b/erpnext/accounts/doctype/bank_account/bank_account.py @@ -115,7 +115,7 @@ def get_party_bank_account(party_type, party): ) -def get_default_company_bank_account(company, party_type, party): +def get_default_company_bank_account(company, party_type, party, ignore_permissions=True): default_company_bank_account = frappe.db.get_value(party_type, party, "default_bank_account") if default_company_bank_account: if company != frappe.get_cached_value("Bank Account", default_company_bank_account, "company"): @@ -126,6 +126,14 @@ def get_default_company_bank_account(company, party_type, party): "Bank Account", {"company": company, "is_company_account": 1, "is_default": 1} ) + if not ignore_permissions: + default_company_bank_account = ( + default_company_bank_account + if default_company_bank_account + and frappe.get_cached_doc("Bank Account", default_company_bank_account).has_permission("select") + else None + ) + return default_company_bank_account diff --git a/erpnext/accounts/doctype/payment_entry/payment_entry.py b/erpnext/accounts/doctype/payment_entry/payment_entry.py index 148dd4edcc5..815bd0fd6f2 100644 --- a/erpnext/accounts/doctype/payment_entry/payment_entry.py +++ b/erpnext/accounts/doctype/payment_entry/payment_entry.py @@ -2691,6 +2691,9 @@ def get_party_details(company, party_type, party, date, cost_center=None): if not frappe.db.exists(party_type, party): frappe.throw(_("{0} {1} does not exist").format(_(party_type), party)) + ptype = "select" if frappe.only_has_select_perm(party_type) else "read" + frappe.has_permission(party_type, ptype, party, throw=True) + party_account = get_party_account(party_type, party, company) account_currency = get_account_currency(party_account) account_balance = ( @@ -2707,7 +2710,7 @@ def get_party_details(company, party_type, party, date, cost_center=None): ) if party_type in ["Customer", "Supplier"]: party_bank_account = get_party_bank_account(party_type, party) - bank_account = get_default_company_bank_account(company, party_type, party) + bank_account = get_default_company_bank_account(company, party_type, party, ignore_permissions=False) return { "party_account": party_account, diff --git a/erpnext/accounts/party.py b/erpnext/accounts/party.py index b39c5a7dc62..2edba2e5c5d 100644 --- a/erpnext/accounts/party.py +++ b/erpnext/accounts/party.py @@ -431,6 +431,17 @@ def get_party_account(party_type, party=None, company=None, include_advance=Fals Will first search in party (Customer / Supplier) record, if not found, will search in group (Customer Group / Supplier Group), finally will return default.""" + + def account_perm_check(account): + ptype = "select" if frappe.only_has_select_perm("Account") else "read" + if frappe.has_permission("Account", ptype, account): + return + + # Using custom message to prevent data leak in case of `apply_strict_permission` is enabled. + frappe.throw( + _("User don't have permissions to select/read this account."), exc=frappe.PermissionError + ) + if not party_type: frappe.throw(_("Party Type is mandatory")) if not company: @@ -441,46 +452,51 @@ def get_party_account(party_type, party=None, company=None, include_advance=Fals "default_receivable_account" if party_type == "Customer" else "default_payable_account" ) - return frappe.get_cached_value("Company", company, default_account_name) - - account = frappe.db.get_value( - "Party Account", {"parenttype": party_type, "parent": party, "company": company}, "account" - ) - - if not account and party_type in ["Customer", "Supplier"]: - party_group_doctype = "Customer Group" if party_type == "Customer" else "Supplier Group" - group = frappe.get_cached_value(party_type, party, scrub(party_group_doctype)) + account = frappe.get_cached_value("Company", company, default_account_name) + else: account = frappe.db.get_value( - "Party Account", - {"parenttype": party_group_doctype, "parent": group, "company": company}, - "account", + "Party Account", {"parenttype": party_type, "parent": party, "company": company}, "account" ) - if not account and party_type in ["Customer", "Supplier"]: - default_account_name = ( - "default_receivable_account" if party_type == "Customer" else "default_payable_account" - ) - account = frappe.get_cached_value("Company", company, default_account_name) + if not account and party_type in ["Customer", "Supplier"]: + party_group_doctype = "Customer Group" if party_type == "Customer" else "Supplier Group" + group = frappe.get_cached_value(party_type, party, scrub(party_group_doctype)) + account = frappe.db.get_value( + "Party Account", + {"parenttype": party_group_doctype, "parent": group, "company": company}, + "account", + ) - existing_gle_currency = get_party_gle_currency(party_type, party, company) - if existing_gle_currency: - if account: - account_currency = frappe.get_cached_value("Account", account, "account_currency") - if (account and account_currency != existing_gle_currency) or not account: - account = get_party_gle_account(party_type, party, company) + if not account and party_type in ["Customer", "Supplier"]: + default_account_name = ( + "default_receivable_account" if party_type == "Customer" else "default_payable_account" + ) + account = frappe.get_cached_value("Company", company, default_account_name) - # get default account on the basis of party type - if not account: - account_type = frappe.get_cached_value("Party Type", party_type, "account_type") - default_account_name = "default_" + account_type.lower() + "_account" - account = frappe.get_cached_value("Company", company, default_account_name) + existing_gle_currency = get_party_gle_currency(party_type, party, company) + if existing_gle_currency: + if account: + account_currency = frappe.get_cached_value("Account", account, "account_currency") + if (account and account_currency != existing_gle_currency) or not account: + account = get_party_gle_account(party_type, party, company) - if include_advance and party_type in ["Customer", "Supplier", "Student"]: + # get default account on the basis of party type + if not account: + account_type = frappe.get_cached_value("Party Type", party_type, "account_type") + default_account_name = "default_" + account_type.lower() + "_account" + account = frappe.get_cached_value("Company", company, default_account_name) + + if account: + account_perm_check(account) + + if include_advance and party and party_type in ["Customer", "Supplier", "Student"]: advance_account = get_party_advance_account(party_type, party, company) + if advance_account: + account_perm_check(advance_account) return [account, advance_account] - else: - return [account] + + return [account] return account diff --git a/erpnext/tests/utils.py b/erpnext/tests/utils.py index 7ed84514f52..7f9f08876be 100644 --- a/erpnext/tests/utils.py +++ b/erpnext/tests/utils.py @@ -114,3 +114,2980 @@ def if_lending_app_not_installed(function): return return wrapper +<<<<<<< HEAD +======= + + +class BootStrapTestData: + def __init__(self): + self.make_presets() + self.make_master_data() + + def make_presets(self): + from frappe.desk.page.setup_wizard.install_fixtures import update_genders, update_salutations + + from erpnext.setup.setup_wizard.operations.install_fixtures import ( + add_uom_data, + get_preset_records, + get_sale_stages, + ) + + update_genders() + update_salutations() + + records = get_preset_records("India") + + from erpnext.setup.setup_wizard.operations.install_fixtures import read_lines + + for doctype, title_field, filename in (("UTM Source", "name", "marketing_source.txt"),): + records += [{"doctype": doctype, title_field: title} for title in read_lines(filename)] + + presets_primary_key_map = { + "Address Template": "country", + "Item Group": "item_group_name", + "Territory": "territory_name", + "Customer Group": "customer_group_name", + "Supplier Group": "supplier_group_name", + "Sales Person": "sales_person_name", + "Mode of Payment": "mode_of_payment", + "Activity Type": "activity_type", + "Item Attribute": "attribute_name", + "Party Type": "party_type", + "Project Type": "project_type", + "Print Heading": "print_heading", + "Share Type": "title", + "Market Segment": "market_segment", + "Workstation Operating Component": "component_name", + } + for x in records: + dt = x.get("doctype") + dn = x.get("name") or x.get(presets_primary_key_map.get(dt)) + + if not frappe.db.exists(dt, dn): + doc = frappe.get_doc(x) + doc.insert() + + add_uom_data() + # add sale stages + for sales_stage in get_sale_stages(): + if not frappe.db.exists("Sales Stage", {"stage_name": sales_stage.get("stage_name")}): + frappe.get_doc(sales_stage).insert() + + from erpnext.buying.doctype.supplier_scorecard.supplier_scorecard import ( + get_default_scorecard_standing, + get_default_scorecard_variables, + ) + + for x in get_default_scorecard_variables(): + x["doctype"] = "Supplier Scorecard Variable" + if not frappe.db.exists("Supplier Scorecard Variable", {"name": x.get("variable_label")}): + frappe.get_doc(x).insert() + for x in get_default_scorecard_standing(): + x["doctype"] = "Supplier Scorecard Standing" + if not frappe.db.exists("Supplier Scorecard Standing", {"name": x.get("standing_name")}): + frappe.get_doc(x).insert() + + frappe.db.commit() # nosemgrep + + def make_master_data(self): + self.update_system_settings() + self.make_fiscal_year() + self.make_holiday_list() + self.make_company() + self.make_test_account() + self.make_supplier_group() + self.make_payment_term() + self.make_payment_terms_template() + self.make_tax_category() + self.make_account() + self.make_supplier() + self.make_role() + self.make_department() + self.make_territory() + self.make_customer_group() + self.make_customer() + self.make_user() + self.make_cost_center() + self.make_warehouse() + self.make_uom() + self.make_item_tax_template() + self.make_item_group() + self.make_item_attribute() + self.make_asset_maintenance_team() + self.make_asset_category() + self.make_item() + self.make_product_bundle() + self.make_location() + self.make_price_list() + self.make_item_price() + self.make_loyalty_program() + self.make_shareholder() + self.make_sales_taxes_template() + self.make_workstation() + self.make_operation() + self.make_bom() + self.make_quality_inspection_param() + self.make_quality_inspection_template() + self.make_employees() + self.make_brand() + self.make_monthly_distribution() + self.make_projects() + self.make_dunning_type() + self.make_finance_book() + self.make_leads() + self.make_sales_person() + self.make_sales_partner() + self.make_activity_type() + self.make_address() + self.make_contact() + self.update_support_settings() + self.update_selling_settings() + self.update_stock_settings() + + frappe.db.commit() # nosemgrep + + # DDL commands have implicit commit + # Dimensions + self.make_dimensions() + + # custom doctype + self.make_custom_doctype() + + # data on custom doctype + self.make_shelf() + self.make_rack() + self.make_inv_site() + self.make_store() + + # custom field + self.make_custom_field() + + def update_system_settings(self): + system_settings = frappe.get_doc("System Settings") + system_settings.time_zone = "Asia/Kolkata" + system_settings.language = "en" + system_settings.currency_precision = system_settings.float_precision = 2 + system_settings.rounding_method = "Banker's Rounding" + system_settings.save() + + def update_support_settings(self): + support_settings = frappe.get_doc("Support Settings") + support_settings.track_service_level_agreement = True + support_settings.save() + + def update_selling_settings(self): + selling_settings = frappe.get_doc("Selling Settings") + selling_settings.selling_price_list = "Standard Selling" + selling_settings.save() + + def update_stock_settings(self): + stock_settings = frappe.get_doc("Stock Settings") + stock_settings.item_naming_by = "Item Code" + stock_settings.valuation_method = "FIFO" + stock_settings.default_warehouse = frappe.db.get_value("Warehouse", {"warehouse_name": _("Stores")}) + stock_settings.stock_uom = "Nos" + stock_settings.auto_indent = 1 + stock_settings.auto_insert_price_list_rate_if_missing = 1 + stock_settings.update_price_list_based_on = "Rate" + stock_settings.set_qty_in_transactions_based_on_serial_no_input = 1 + stock_settings.enable_serial_and_batch_no_for_item = 1 + stock_settings.save() + + def make_records(self, key, records): + doctype = records[0].get("doctype") + + def get_filters(record): + filters = {} + for x in key: + filters[x] = record.get(x) + return filters + + for x in records: + filters = get_filters(x) + if not frappe.db.exists(doctype, filters): + frappe.get_doc(x).insert() + + def make_price_list(self): + records = [ + { + "doctype": "Price List", + "price_list_name": _("Standard Buying"), + "enabled": 1, + "buying": 1, + "selling": 0, + "currency": "INR", + }, + { + "doctype": "Price List", + "price_list_name": _("Standard Selling"), + "enabled": 1, + "buying": 0, + "selling": 1, + "currency": "INR", + }, + { + "buying": 1, + "currency": "INR", + "doctype": "Price List", + "enabled": 1, + "price_not_uom_dependant": 1, + "price_list_name": "_Test Price List", + "selling": 1, + }, + { + "buying": 1, + "currency": "INR", + "doctype": "Price List", + "enabled": 1, + "price_list_name": "_Test Price List 2", + "selling": 1, + }, + { + "buying": 1, + "currency": "INR", + "doctype": "Price List", + "enabled": 1, + "price_list_name": "_Test Price List India", + "selling": 1, + }, + { + "buying": 1, + "currency": "USD", + "doctype": "Price List", + "enabled": 1, + "price_list_name": "_Test Price List Rest of the World", + "selling": 1, + }, + { + "buying": 0, + "currency": "USD", + "doctype": "Price List", + "enabled": 1, + "price_list_name": "_Test Selling Price List", + "selling": 1, + }, + { + "buying": 1, + "currency": "USD", + "doctype": "Price List", + "enabled": 1, + "price_list_name": "_Test Buying Price List", + "selling": 0, + }, + ] + self.make_records(["price_list_name", "enabled", "selling", "buying", "currency"], records) + + def make_monthly_distribution(self): + records = [ + { + "doctype": "Monthly Distribution", + "distribution_id": "_Test Distribution", + "fiscal_year": "_Test Fiscal Year 2013", + "percentages": [ + {"month": "January", "percentage_allocation": "8"}, + {"month": "February", "percentage_allocation": "8"}, + {"month": "March", "percentage_allocation": "8"}, + {"month": "April", "percentage_allocation": "8"}, + {"month": "May", "percentage_allocation": "8"}, + {"month": "June", "percentage_allocation": "8"}, + {"month": "July", "percentage_allocation": "8"}, + {"month": "August", "percentage_allocation": "8"}, + {"month": "September", "percentage_allocation": "8"}, + {"month": "October", "percentage_allocation": "8"}, + {"month": "November", "percentage_allocation": "10"}, + {"month": "December", "percentage_allocation": "10"}, + ], + } + ] + self.make_records(["distribution_id"], records) + + def make_projects(self): + records = [ + { + "doctype": "Project", + "company": "_Test Company", + "project_name": "_Test Project", + "status": "Open", + } + ] + self.make_records(["project_name"], records) + + def make_customer_group(self): + records = [ + { + "customer_group_name": "_Test Customer Group", + "doctype": "Customer Group", + "is_group": 0, + "parent_customer_group": "All Customer Groups", + }, + { + "customer_group_name": "_Test Customer Group 1", + "doctype": "Customer Group", + "is_group": 0, + "parent_customer_group": "All Customer Groups", + }, + ] + self.make_records(["customer_group_name"], records) + + def make_territory(self): + records = [ + { + "doctype": "Territory", + "is_group": 0, + "parent_territory": "All Territories", + "territory_name": "_Test Territory", + }, + { + "doctype": "Territory", + "is_group": 1, + "parent_territory": "All Territories", + "territory_name": "_Test Territory India", + }, + { + "doctype": "Territory", + "is_group": 0, + "parent_territory": "_Test Territory India", + "territory_name": "_Test Territory Maharashtra", + }, + { + "doctype": "Territory", + "is_group": 0, + "parent_territory": "All Territories", + "territory_name": "_Test Territory Rest Of The World", + }, + { + "doctype": "Territory", + "is_group": 0, + "parent_territory": "All Territories", + "territory_name": "_Test Territory United States", + }, + ] + self.make_records(["territory_name"], records) + + def make_department(self): + records = [ + { + "doctype": "Department", + "department_name": "_Test Department", + "company": "_Test Company", + "parent_department": "All Departments", + }, + { + "doctype": "Department", + "department_name": "_Test Department 1", + "company": "_Test Company", + "parent_department": "All Departments", + }, + ] + self.make_records(["department_name"], records) + + def make_role(self): + records = [ + {"doctype": "Role", "role_name": "_Test Role", "desk_access": 1}, + {"doctype": "Role", "role_name": "_Test Role 2", "desk_access": 1}, + {"doctype": "Role", "role_name": "_Test Role 3", "desk_access": 1}, + {"doctype": "Role", "role_name": "_Test Role 4", "desk_access": 0}, + {"doctype": "Role", "role_name": "Technician"}, + ] + self.make_records(["role_name"], records) + + def make_user(self): + records = [ + { + "doctype": "User", + "email": "test@example.com", + "enabled": 1, + "first_name": "_Test", + "new_password": "Eastern_43A1W", + "roles": [ + {"doctype": "Has Role", "parentfield": "roles", "role": "_Test Role"}, + {"doctype": "Has Role", "parentfield": "roles", "role": "Accounts User"}, + {"doctype": "Has Role", "parentfield": "roles", "role": "System Manager"}, + ], + }, + { + "doctype": "User", + "email": "test1@example.com", + "first_name": "_Test1", + "new_password": "Eastern_43A1W", + }, + { + "doctype": "User", + "email": "test2@example.com", + "first_name": "_Test2", + "new_password": "Eastern_43A1W", + "enabled": 1, + }, + { + "doctype": "User", + "email": "test3@example.com", + "first_name": "_Test3", + "new_password": "Eastern_43A1W", + "enabled": 1, + }, + { + "doctype": "User", + "email": "test4@example.com", + "first_name": "_Test4", + "new_password": "Eastern_43A1W", + "enabled": 1, + }, + { + "doctype": "User", + "email": "test'5@example.com", + "first_name": "_Test'5", + "new_password": "Eastern_43A1W", + "enabled": 1, + }, + { + "doctype": "User", + "email": "testperm@example.com", + "first_name": "_Test Perm", + "new_password": "Eastern_43A1W", + "enabled": 1, + }, + { + "doctype": "User", + "email": "testdelete@example.com", + "enabled": 1, + "first_name": "_Test", + "new_password": "Eastern_43A1W", + "roles": [ + {"doctype": "Has Role", "parentfield": "roles", "role": "_Test Role 2"}, + {"doctype": "Has Role", "parentfield": "roles", "role": "System Manager"}, + ], + }, + { + "doctype": "User", + "email": "testpassword@example.com", + "enabled": 1, + "first_name": "_Test", + "new_password": "Eastern_43A1W", + "roles": [{"doctype": "Has Role", "parentfield": "roles", "role": "System Manager"}], + }, + { + "doctype": "User", + "email": "marcus@abc.com", + "first_name": "marcus@abc.com", + "new_password": "password", + "roles": [{"doctype": "Has Role", "role": "Technician"}], + }, + { + "doctype": "User", + "email": "thalia@abc.com", + "first_name": "thalia@abc.com", + "new_password": "password", + "roles": [{"doctype": "Has Role", "role": "Technician"}], + }, + { + "doctype": "User", + "email": "mathias@abc.com", + "first_name": "mathias@abc.com", + "new_password": "password", + "roles": [{"doctype": "Has Role", "role": "Technician"}], + }, + ] + self.make_records(["email"], records) + + def make_employees(self): + records = [ + { + "company": "_Test Company", + "date_of_birth": "1980-01-01", + "date_of_joining": "2010-01-01", + "department": "_Test Department - _TC", + "doctype": "Employee", + "first_name": "_Test Employee", + "gender": "Female", + "naming_series": "_T-Employee-", + "status": "Active", + "user_id": "test@example.com", + }, + { + "company": "_Test Company", + "date_of_birth": "1980-01-01", + "date_of_joining": "2010-01-01", + "department": "_Test Department 1 - _TC", + "doctype": "Employee", + "first_name": "_Test Employee 1", + "gender": "Male", + "naming_series": "_T-Employee-", + "status": "Active", + "user_id": "test1@example.com", + }, + { + "company": "_Test Company", + "date_of_birth": "1980-01-01", + "date_of_joining": "2010-01-01", + "department": "_Test Department 1 - _TC", + "doctype": "Employee", + "first_name": "_Test Employee 2", + "gender": "Male", + "naming_series": "_T-Employee-", + "status": "Active", + "user_id": "test2@example.com", + }, + ] + self.make_records(["first_name"], records) + + def make_sales_person(self): + records = [ + { + "doctype": "Sales Person", + "employee": "_T-Employee-00001", + "is_group": 0, + "parent_sales_person": "Sales Team", + "sales_person_name": "_Test Sales Person", + }, + { + "doctype": "Sales Person", + "employee": "_T-Employee-00002", + "is_group": 0, + "parent_sales_person": "Sales Team", + "sales_person_name": "_Test Sales Person 1", + }, + { + "doctype": "Sales Person", + "employee": "_T-Employee-00003", + "is_group": 0, + "parent_sales_person": "Sales Team", + "sales_person_name": "_Test Sales Person 2", + }, + ] + self.make_records(["sales_person_name"], records) + + def make_sales_partner(self): + records = [ + { + "doctype": "Sales Partner", + "partner_name": "_Test Sales Partner India - 1", + "commission_rate": 7, + "territory": "_Test Territory India", + }, + { + "doctype": "Sales Partner", + "partner_name": "_Test Sales Partner India - 2", + "commission_rate": 5, + "territory": "_Test Territory India", + }, + { + "doctype": "Sales Partner", + "partner_name": "_Test Sales Partner Global - 1", + "commission_rate": 8, + "territory": "_Test Territory Rest Of The World", + }, + ] + self.make_records(["partner_name"], records) + + def make_leads(self): + records = [ + { + "doctype": "Lead", + "email_id": "test_lead@example.com", + "lead_name": "_Test Lead", + "status": "Open", + "territory": "_Test Territory", + "naming_series": "_T-Lead-", + }, + { + "doctype": "Lead", + "email_id": "test_lead1@example.com", + "lead_name": "_Test Lead 1", + "status": "Open", + "naming_series": "_T-Lead-", + }, + { + "doctype": "Lead", + "email_id": "test_lead2@example.com", + "lead_name": "_Test Lead 2", + "status": "Lead", + "naming_series": "_T-Lead-", + }, + { + "doctype": "Lead", + "email_id": "test_lead3@example.com", + "lead_name": "_Test Lead 3", + "status": "Converted", + "naming_series": "_T-Lead-", + }, + { + "doctype": "Lead", + "email_id": "test_lead4@example.com", + "lead_name": "_Test Lead 4", + "company_name": "_Test Lead 4", + "status": "Open", + "naming_series": "_T-Lead-", + }, + ] + self.make_records(["email_id"], records) + + def make_holiday_list(self): + records = [ + { + "doctype": "Holiday List", + "from_date": "2013-01-01", + "to_date": "2013-12-31", + "holidays": [ + {"description": "New Year", "holiday_date": "2013-01-01"}, + {"description": "Republic Day", "holiday_date": "2013-01-26"}, + {"description": "Test Holiday", "holiday_date": "2013-02-01"}, + ], + "holiday_list_name": "_Test Holiday List", + } + ] + self.make_records(["holiday_list_name"], records) + + def make_company(self): + records = load_test_records_for("Company")["Company"] + self.make_records(["company_name"], records) + + def make_fiscal_year(self): + records = [ + { + "doctype": "Fiscal Year", + "year": "_Test Short Fiscal Year 2011", + "is_short_year": 1, + "year_start_date": "2011-04-01", + "year_end_date": "2011-12-31", + } + ] + + start = 2012 + end = now_datetime().year + 25 + for year in range(start, end): + records.append( + { + "doctype": "Fiscal Year", + "year": f"_Test Fiscal Year {year}", + "year_start_date": f"{year}-01-01", + "year_end_date": f"{year}-12-31", + } + ) + + key = ["year_start_date", "year_end_date"] + self.make_records(key, records) + + def make_payment_term(self): + records = [ + { + "doctype": "Payment Term", + "due_date_based_on": "Day(s) after invoice date", + "payment_term_name": "_Test N30", + "description": "_Test Net 30 Days", + "invoice_portion": 50, + "credit_days": 30, + }, + { + "doctype": "Payment Term", + "due_date_based_on": "Day(s) after invoice date", + "payment_term_name": "_Test COD", + "description": "_Test Cash on Delivery", + "invoice_portion": 50, + "credit_days": 0, + }, + { + "doctype": "Payment Term", + "due_date_based_on": "Month(s) after the end of the invoice month", + "payment_term_name": "_Test EONM", + "description": "_Test End of Next Month", + "invoice_portion": 100, + "credit_months": 1, + }, + { + "doctype": "Payment Term", + "due_date_based_on": "Day(s) after invoice date", + "payment_term_name": "_Test N30 1", + "description": "_Test Net 30 Days", + "invoice_portion": 100, + "credit_days": 30, + }, + ] + self.make_records(["payment_term_name"], records) + + def make_payment_terms_template(self): + records = [ + { + "doctype": "Payment Terms Template", + "terms": [ + { + "doctype": "Payment Terms Template Detail", + "due_date_based_on": "Day(s) after invoice date", + "idx": 1, + "description": "Cash on Delivery", + "invoice_portion": 50, + "credit_days": 0, + "credit_months": 0, + "payment_term": "_Test COD", + }, + { + "doctype": "Payment Terms Template Detail", + "due_date_based_on": "Day(s) after invoice date", + "idx": 2, + "description": "Net 30 Days ", + "invoice_portion": 50, + "credit_days": 30, + "credit_months": 0, + "payment_term": "_Test N30", + }, + ], + "template_name": "_Test Payment Term Template", + }, + { + "doctype": "Payment Terms Template", + "terms": [ + { + "doctype": "Payment Terms Template Detail", + "due_date_based_on": "Month(s) after the end of the invoice month", + "idx": 1, + "description": "_Test End of Next Months", + "invoice_portion": 100, + "credit_days": 0, + "credit_months": 1, + "payment_term": "_Test EONM", + } + ], + "template_name": "_Test Payment Term Template 1", + }, + { + "doctype": "Payment Terms Template", + "terms": [ + { + "doctype": "Payment Terms Template Detail", + "due_date_based_on": "Day(s) after invoice date", + "idx": 1, + "description": "_Test Net Within 30 days", + "invoice_portion": 100, + "credit_days": 30, + "credit_months": 0, + "payment_term": "_Test N30 1", + } + ], + "template_name": "_Test Payment Term Template 3", + }, + ] + self.make_records(["template_name"], records) + + def make_tax_category(self): + records = [ + {"doctype": "Tax Category", "name": "_Test Tax Category 1", "title": "_Test Tax Category 1"}, + {"doctype": "Tax Category", "name": "_Test Tax Category 2", "title": "_Test Tax Category 2"}, + {"doctype": "Tax Category", "name": "_Test Tax Category 3", "title": "_Test Tax Category 3"}, + ] + self.make_records(["title"], records) + + def make_account(self): + records = [ + { + "doctype": "Account", + "account_name": "_Test Payable USD", + "parent_account": "Accounts Receivable - _TC", + "company": "_Test Company", + "account_currency": "USD", + }, + { + "doctype": "Account", + "account_name": "_Test Bank", + "parent_account": "Bank Accounts - _TC", + "company": "_Test Company", + }, + { + "doctype": "Account", + "account_name": "_Test Bank", + "parent_account": "Bank Accounts - TCP1", + "company": "_Test Company with perpetual inventory", + }, + ] + self.make_records(["account_name", "company"], records) + + def make_supplier(self): + records = [ + { + "doctype": "Supplier", + "supplier_name": "_Test Supplier With Template 1", + "supplier_group": "_Test Supplier Group", + "payment_terms": "_Test Payment Term Template 3", + }, + { + "doctype": "Supplier", + "supplier_name": "_Test Supplier P", + "supplier_group": "_Test Supplier Group", + }, + { + "doctype": "Supplier", + "supplier_name": "_Test Supplier with Country", + "supplier_group": "_Test Supplier Group", + "country": "Greece", + }, + { + "doctype": "Supplier", + "supplier_name": "_Test Supplier", + "supplier_group": "_Test Supplier Group", + }, + { + "doctype": "Supplier", + "supplier_name": "_Test Supplier 1", + "supplier_group": "_Test Supplier Group", + }, + { + "doctype": "Supplier", + "supplier_name": "_Test Supplier 2", + "supplier_group": "_Test Supplier Group", + }, + { + "doctype": "Supplier", + "supplier_name": "_Test Supplier USD", + "supplier_group": "_Test Supplier Group", + "default_currency": "USD", + "accounts": [{"company": "_Test Company", "account": "_Test Payable USD - _TC"}], + }, + { + "doctype": "Supplier", + "supplier_name": "_Test Another Supplier USD", + "supplier_group": "_Test Supplier Group", + "default_currency": "USD", + "accounts": [{"company": "_Test Company", "account": "_Test Payable USD - _TC"}], + }, + { + "doctype": "Supplier", + "supplier_name": "_Test Supplier With Tax Category", + "supplier_group": "_Test Supplier Group", + "tax_category": "_Test Tax Category 1", + }, + { + "doctype": "Supplier", + "supplier_name": "_Test Internal Supplier 2", + "supplier_group": "_Test Supplier Group", + "is_internal_supplier": 1, + "territory": "_Test Territory", + "represents_company": "_Test Company with perpetual inventory", + "companies": [{"company": "_Test Company with perpetual inventory"}], + }, + ] + self.make_records(["supplier_name"], records) + + def make_supplier_group(self): + records = [ + { + "doctype": "Supplier Group", + "supplier_group_name": "_Test Supplier Group", + "parent_supplier_group": "All Supplier Groups", + } + ] + self.make_records(["supplier_group_name"], records) + + def make_cost_center(self): + records = [ + { + "company": "_Test Company", + "cost_center_name": "_Test Cost Center", + "doctype": "Cost Center", + "is_group": 0, + "parent_cost_center": "_Test Company - _TC", + }, + { + "company": "_Test Company", + "cost_center_name": "_Test Cost Center 2", + "doctype": "Cost Center", + "is_group": 0, + "parent_cost_center": "_Test Company - _TC", + }, + { + "company": "_Test Company", + "cost_center_name": "_Test Write Off Cost Center", + "doctype": "Cost Center", + "is_group": 0, + "parent_cost_center": "_Test Company - _TC", + }, + { + "company": "_Test Company", + "cost_center_name": "Sub", + "doctype": "Cost Center", + "is_group": 0, + "parent_cost_center": "_Test Company - _TC", + }, + ] + self.make_records(["cost_center_name", "company"], records) + + def make_location(self): + records = [ + {"doctype": "Location", "location_name": "Test Location"}, + {"doctype": "Location", "location_name": "Test Location 2"}, + {"doctype": "Location", "location_name": "Test Location Area", "is_group": 1, "is_container": 1}, + { + "doctype": "Location", + "location_name": "Basil Farm", + "location": '{"type":"FeatureCollection","features":[{"type":"Feature","properties":{"point_type":"circle","radius":884.5625420736483},"geometry":{"type":"Point","coordinates":[72.875834,19.100566]}}]}', + "parent_location": "Test Location Area", + "parent": "Test Location Area", + "is_group": 1, + "is_container": 1, + }, + { + "doctype": "Location", + "location_name": "Division 1", + "location": '{"type":"FeatureCollection","features":[{"type":"Feature","properties":{"point_type":"circle","radius":542.3424997060739},"geometry":{"type":"Point","coordinates":[72.852359,19.11557]}}]}', + "parent_location": "Basil Farm", + "parent": "Basil Farm", + "is_group": 1, + "is_container": 1, + }, + { + "doctype": "Location", + "location_name": "Field 1", + "location": '{"type":"FeatureCollection","features":[{"type":"Feature","properties":{},"geometry":{"type":"Polygon","coordinates":[[[72.846758,19.118287],[72.846758,19.121206],[72.850535,19.121206],[72.850535,19.118287],[72.846758,19.118287]]]}}]}', + "parent_location": "Division 1", + "parent": "Division 1", + "is_group": 1, + "is_container": 1, + }, + { + "doctype": "Location", + "location_name": "Block 1", + "location": '{"type":"FeatureCollection","features":[{"type":"Feature","properties":{},"geometry":{"type":"Polygon","coordinates":[[[72.921495,19.073313],[72.924929,19.068121],[72.934713,19.06585],[72.929392,19.05579],[72.94158,19.056926],[72.951365,19.095213],[72.921495,19.073313]]]}}]}', + "parent_location": "Field 1", + "parent": "Field 1", + "is_group": 0, + "is_container": 1, + }, + ] + self.make_records(["location_name"], records) + + def make_warehouse(self): + records = [ + { + "company": "_Test Company", + "doctype": "Warehouse", + "warehouse_name": "_Test Warehouse", + "is_group": 0, + }, + { + "company": "_Test Company", + "doctype": "Warehouse", + "warehouse_name": "_Test Scrap Warehouse", + "is_group": 0, + }, + { + "company": "_Test Company", + "doctype": "Warehouse", + "warehouse_name": "_Test Warehouse 1", + "is_group": 0, + }, + { + "company": "_Test Company", + "doctype": "Warehouse", + "warehouse_name": "_Test Warehouse 2", + "is_group": 0, + }, + { + "company": "_Test Company", + "doctype": "Warehouse", + "warehouse_name": "_Test Rejected Warehouse", + "is_group": 0, + }, + { + "company": "_Test Company 1", + "doctype": "Warehouse", + "warehouse_name": "_Test Warehouse 2", + "is_group": 0, + }, + { + "company": "_Test Company", + "doctype": "Warehouse", + "warehouse_name": "_Test Warehouse No Account", + "is_group": 0, + }, + { + "company": "_Test Company", + "doctype": "Warehouse", + "warehouse_name": "_Test Warehouse Group", + "is_group": 1, + }, + { + "company": "_Test Company", + "doctype": "Warehouse", + "warehouse_name": "_Test Warehouse Group-C1", + "is_group": 0, + "parent_warehouse": "_Test Warehouse Group - _TC", + }, + { + "company": "_Test Company", + "doctype": "Warehouse", + "warehouse_name": "_Test Warehouse Group-C2", + "is_group": 0, + "parent_warehouse": "_Test Warehouse Group - _TC", + }, + { + "company": "_Test Company", + "doctype": "Warehouse", + "warehouse_name": "_Test Warehouse for Stock Reco1", + "is_group": 0, + }, + { + "company": "_Test Company", + "doctype": "Warehouse", + "warehouse_name": "_Test Warehouse for Stock Reco2", + "is_group": 0, + }, + ] + self.make_records(["warehouse_name", "company"], records) + + def make_uom(self): + records = [ + {"doctype": "UOM", "must_be_whole_number": 1, "uom_name": "_Test UOM"}, + {"doctype": "UOM", "uom_name": "_Test UOM 1"}, + ] + self.make_records(["uom_name"], records) + + def make_item_attribute(self): + records = [ + { + "doctype": "Item Attribute", + "attribute_name": "Test Size", + "priority": 1, + "item_attribute_values": [ + {"attribute_value": "Extra Small", "abbr": "XSL"}, + {"attribute_value": "Small", "abbr": "S"}, + {"attribute_value": "Medium", "abbr": "M"}, + {"attribute_value": "Large", "abbr": "L"}, + {"attribute_value": "Extra Large", "abbr": "XL"}, + {"attribute_value": "2XL", "abbr": "2XL"}, + ], + }, + { + "doctype": "Item Attribute", + "attribute_name": "Test Colour", + "priority": 2, + "item_attribute_values": [ + {"attribute_value": "Red", "abbr": "R"}, + {"attribute_value": "Green", "abbr": "G"}, + {"attribute_value": "Blue", "abbr": "B"}, + ], + }, + ] + self.make_records(["attribute_name"], records) + + def make_item_tax_template(self): + records = [ + { + "doctype": "Item Tax Template", + "title": "_Test Account Excise Duty @ 10", + "company": "_Test Company", + "taxes": [ + { + "doctype": "Item Tax Template Detail", + "parentfield": "taxes", + "tax_rate": 10, + "tax_type": "_Test Account Excise Duty - _TC", + } + ], + }, + { + "doctype": "Item Tax Template", + "title": "_Test Account Excise Duty @ 12", + "company": "_Test Company", + "taxes": [ + { + "doctype": "Item Tax Template Detail", + "parentfield": "taxes", + "tax_rate": 12, + "tax_type": "_Test Account Excise Duty - _TC", + } + ], + }, + { + "doctype": "Item Tax Template", + "title": "_Test Account Excise Duty @ 15", + "company": "_Test Company", + "taxes": [ + { + "doctype": "Item Tax Template Detail", + "parentfield": "taxes", + "tax_rate": 15, + "tax_type": "_Test Account Excise Duty - _TC", + } + ], + }, + { + "doctype": "Item Tax Template", + "title": "_Test Account Excise Duty @ 20", + "company": "_Test Company", + "taxes": [ + { + "doctype": "Item Tax Template Detail", + "parentfield": "taxes", + "tax_rate": 20, + "tax_type": "_Test Account Excise Duty - _TC", + } + ], + }, + { + "doctype": "Item Tax Template", + "title": "_Test Item Tax Template 1", + "company": "_Test Company", + "taxes": [ + { + "doctype": "Item Tax Template Detail", + "parentfield": "taxes", + "tax_rate": 5, + "tax_type": "_Test Account Excise Duty - _TC", + }, + { + "doctype": "Item Tax Template Detail", + "parentfield": "taxes", + "tax_rate": 10, + "tax_type": "_Test Account Education Cess - _TC", + }, + { + "doctype": "Item Tax Template Detail", + "parentfield": "taxes", + "tax_rate": 15, + "tax_type": "_Test Account S&H Education Cess - _TC", + }, + ], + }, + ] + self.make_records(["title", "company"], records) + + def make_item_group(self): + records = [ + { + "doctype": "Item Group", + "is_group": 0, + "item_group_name": "_Test Item Group", + "parent_item_group": "All Item Groups", + "item_group_defaults": [ + { + "company": "_Test Company", + "buying_cost_center": "_Test Cost Center 2 - _TC", + "selling_cost_center": "_Test Cost Center 2 - _TC", + "default_warehouse": "_Test Warehouse - _TC", + } + ], + }, + { + "doctype": "Item Group", + "is_group": 0, + "item_group_name": "_Test Item Group Desktops", + "parent_item_group": "All Item Groups", + }, + { + "doctype": "Item Group", + "is_group": 1, + "item_group_name": "_Test Item Group A", + "parent_item_group": "All Item Groups", + }, + { + "doctype": "Item Group", + "is_group": 1, + "item_group_name": "_Test Item Group B", + "parent_item_group": "All Item Groups", + }, + { + "doctype": "Item Group", + "is_group": 1, + "item_group_name": "_Test Item Group B - 1", + "parent_item_group": "_Test Item Group B", + }, + { + "doctype": "Item Group", + "is_group": 1, + "item_group_name": "_Test Item Group B - 2", + "parent_item_group": "_Test Item Group B", + }, + { + "doctype": "Item Group", + "is_group": 0, + "item_group_name": "_Test Item Group B - 3", + "parent_item_group": "_Test Item Group B", + }, + { + "doctype": "Item Group", + "is_group": 1, + "item_group_name": "_Test Item Group C", + "parent_item_group": "All Item Groups", + }, + { + "doctype": "Item Group", + "is_group": 1, + "item_group_name": "_Test Item Group C - 1", + "parent_item_group": "_Test Item Group C", + }, + { + "doctype": "Item Group", + "is_group": 1, + "item_group_name": "_Test Item Group C - 2", + "parent_item_group": "_Test Item Group C", + }, + { + "doctype": "Item Group", + "is_group": 1, + "item_group_name": "_Test Item Group D", + "parent_item_group": "All Item Groups", + }, + { + "doctype": "Item Group", + "is_group": 1, + "item_group_name": "_Test Item Group Tax Parent", + "parent_item_group": "All Item Groups", + "taxes": [ + { + "doctype": "Item Tax", + "parentfield": "taxes", + "item_tax_template": "_Test Account Excise Duty @ 10 - _TC", + "tax_category": "", + }, + { + "doctype": "Item Tax", + "parentfield": "taxes", + "item_tax_template": "_Test Account Excise Duty @ 12 - _TC", + "tax_category": "_Test Tax Category 1", + }, + ], + }, + { + "doctype": "Item Group", + "is_group": 0, + "item_group_name": "_Test Item Group Tax Child Override", + "parent_item_group": "_Test Item Group Tax Parent", + "taxes": [ + { + "doctype": "Item Tax", + "parentfield": "taxes", + "item_tax_template": "_Test Account Excise Duty @ 15 - _TC", + "tax_category": "", + } + ], + }, + ] + self.make_records(["item_group_name"], records) + + def make_item(self): + records = [ + { + "description": "_Test Item 1", + "doctype": "Item", + "has_batch_no": 0, + "has_serial_no": 0, + "inspection_required": 0, + "is_stock_item": 1, + "is_sub_contracted_item": 0, + "item_code": "_Test Item", + "item_group": "_Test Item Group", + "item_name": "_Test Item", + "apply_warehouse_wise_reorder_level": 1, + "opening_stock": 10, + "valuation_rate": 100, + "allow_negative_stock": True, + "item_defaults": [ + { + "company": "_Test Company", + "default_warehouse": "_Test Warehouse - _TC", + "expense_account": "_Test Account Cost for Goods Sold - _TC", + "buying_cost_center": "_Test Cost Center - _TC", + "selling_cost_center": "_Test Cost Center - _TC", + "income_account": "Sales - _TC", + } + ], + "reorder_levels": [ + { + "material_request_type": "Purchase", + "warehouse": "_Test Warehouse - _TC", + "warehouse_reorder_level": 20, + "warehouse_reorder_qty": 20, + } + ], + "uoms": [ + {"uom": "_Test UOM", "conversion_factor": 1.0}, + {"uom": "_Test UOM 1", "conversion_factor": 10.0}, + ], + "stock_uom": "_Test UOM", + }, + { + "description": "_Test Item 2", + "doctype": "Item", + "has_batch_no": 0, + "has_serial_no": 0, + "inspection_required": 0, + "is_stock_item": 1, + "is_sub_contracted_item": 0, + "item_code": "_Test Item 2", + "item_group": "_Test Item Group", + "item_name": "_Test Item 2", + "stock_uom": "_Test UOM", + "opening_stock": 10, + "valuation_rate": 100, + "item_defaults": [ + { + "company": "_Test Company", + "default_warehouse": "_Test Warehouse - _TC", + "expense_account": "_Test Account Cost for Goods Sold - _TC", + "buying_cost_center": "_Test Cost Center - _TC", + "selling_cost_center": "_Test Cost Center - _TC", + "income_account": "Sales - _TC", + } + ], + }, + { + "description": "_Test Item Home Desktop 100 3", + "doctype": "Item", + "has_batch_no": 0, + "has_serial_no": 0, + "inspection_required": 0, + "is_stock_item": 1, + "is_sub_contracted_item": 0, + "item_code": "_Test Item Home Desktop 100", + "item_group": "_Test Item Group Desktops", + "item_name": "_Test Item Home Desktop 100", + "valuation_rate": 100, + "item_defaults": [ + { + "company": "_Test Company", + "default_warehouse": "_Test Warehouse - _TC", + "expense_account": "_Test Account Cost for Goods Sold - _TC", + "buying_cost_center": "_Test Cost Center - _TC", + "selling_cost_center": "_Test Cost Center - _TC", + "income_account": "Sales - _TC", + } + ], + "taxes": [ + { + "doctype": "Item Tax", + "parentfield": "taxes", + "item_tax_template": "_Test Account Excise Duty @ 10 - _TC", + } + ], + "stock_uom": "_Test UOM 1", + }, + { + "description": "_Test Item Home Desktop 200 4", + "doctype": "Item", + "has_batch_no": 0, + "has_serial_no": 0, + "inspection_required": 0, + "is_sub_contracted_item": 0, + "item_code": "_Test Item Home Desktop 200", + "item_group": "_Test Item Group Desktops", + "item_name": "_Test Item Home Desktop 200", + "stock_uom": "_Test UOM 1", + "item_defaults": [ + { + "company": "_Test Company", + "default_warehouse": "_Test Warehouse - _TC", + "expense_account": "_Test Account Cost for Goods Sold - _TC", + "buying_cost_center": "_Test Cost Center - _TC", + "selling_cost_center": "_Test Cost Center - _TC", + "income_account": "Sales - _TC", + } + ], + }, + { + "description": "_Test Product Bundle Item 5", + "doctype": "Item", + "has_batch_no": 0, + "has_serial_no": 0, + "inspection_required": 0, + "is_stock_item": 0, + "is_sub_contracted_item": 0, + "item_code": "_Test Product Bundle Item", + "item_group": "_Test Item Group Desktops", + "item_name": "_Test Product Bundle Item", + "stock_uom": "_Test UOM", + "item_defaults": [ + { + "company": "_Test Company", + "default_warehouse": "_Test Warehouse - _TC", + "expense_account": "_Test Account Cost for Goods Sold - _TC", + "buying_cost_center": "_Test Cost Center - _TC", + "selling_cost_center": "_Test Cost Center - _TC", + "income_account": "Sales - _TC", + } + ], + }, + { + "description": "_Test FG Item 6", + "doctype": "Item", + "has_batch_no": 0, + "has_serial_no": 0, + "inspection_required": 0, + "is_stock_item": 1, + "is_sub_contracted_item": 1, + "item_code": "_Test FG Item", + "item_group": "_Test Item Group Desktops", + "item_name": "_Test FG Item", + "stock_uom": "_Test UOM", + "item_defaults": [ + { + "company": "_Test Company", + "default_warehouse": "_Test Warehouse - _TC", + "expense_account": "_Test Account Cost for Goods Sold - _TC", + "buying_cost_center": "_Test Cost Center - _TC", + "selling_cost_center": "_Test Cost Center - _TC", + "income_account": "Sales - _TC", + } + ], + }, + { + "description": "_Test Non Stock Item 7", + "doctype": "Item", + "has_batch_no": 0, + "has_serial_no": 0, + "inspection_required": 0, + "is_stock_item": 0, + "is_sub_contracted_item": 0, + "item_code": "_Test Non Stock Item", + "item_group": "_Test Item Group Desktops", + "item_name": "_Test Non Stock Item", + "stock_uom": "_Test UOM", + "item_defaults": [ + { + "company": "_Test Company", + "default_warehouse": "_Test Warehouse - _TC", + "expense_account": "_Test Account Cost for Goods Sold - _TC", + "buying_cost_center": "_Test Cost Center - _TC", + "selling_cost_center": "_Test Cost Center - _TC", + "income_account": "Sales - _TC", + } + ], + }, + { + "description": "_Test Serialized Item 8", + "doctype": "Item", + "has_batch_no": 0, + "has_serial_no": 1, + "inspection_required": 0, + "is_stock_item": 1, + "is_sub_contracted_item": 0, + "item_code": "_Test Serialized Item", + "item_group": "_Test Item Group Desktops", + "item_name": "_Test Serialized Item", + "stock_uom": "_Test UOM", + "item_defaults": [ + { + "company": "_Test Company", + "default_warehouse": "_Test Warehouse - _TC", + "expense_account": "_Test Account Cost for Goods Sold - _TC", + "buying_cost_center": "_Test Cost Center - _TC", + "selling_cost_center": "_Test Cost Center - _TC", + "income_account": "Sales - _TC", + } + ], + }, + { + "description": "_Test Serialized Item 9", + "doctype": "Item", + "has_batch_no": 0, + "has_serial_no": 1, + "inspection_required": 0, + "is_stock_item": 1, + "is_sub_contracted_item": 0, + "item_code": "_Test Serialized Item With Series", + "item_group": "_Test Item Group Desktops", + "item_name": "_Test Serialized Item With Series", + "serial_no_series": "ABCD.#####", + "stock_uom": "_Test UOM", + "item_defaults": [ + { + "company": "_Test Company", + "default_warehouse": "_Test Warehouse - _TC", + "expense_account": "_Test Account Cost for Goods Sold - _TC", + "buying_cost_center": "_Test Cost Center - _TC", + "selling_cost_center": "_Test Cost Center - _TC", + "income_account": "Sales - _TC", + } + ], + }, + { + "description": "_Test Item Home Desktop Manufactured 10", + "doctype": "Item", + "has_batch_no": 0, + "has_serial_no": 0, + "inspection_required": 0, + "is_stock_item": 1, + "is_sub_contracted_item": 0, + "item_code": "_Test Item Home Desktop Manufactured", + "item_group": "_Test Item Group Desktops", + "item_name": "_Test Item Home Desktop Manufactured", + "stock_uom": "_Test UOM", + "item_defaults": [ + { + "company": "_Test Company", + "default_warehouse": "_Test Warehouse - _TC", + "expense_account": "_Test Account Cost for Goods Sold - _TC", + "buying_cost_center": "_Test Cost Center - _TC", + "selling_cost_center": "_Test Cost Center - _TC", + "income_account": "Sales - _TC", + } + ], + }, + { + "description": "_Test FG Item 2 11", + "doctype": "Item", + "has_batch_no": 0, + "has_serial_no": 0, + "inspection_required": 0, + "is_stock_item": 1, + "is_sub_contracted_item": 1, + "item_code": "_Test FG Item 2", + "item_group": "_Test Item Group Desktops", + "item_name": "_Test FG Item 2", + "stock_uom": "_Test UOM", + "item_defaults": [ + { + "company": "_Test Company", + "default_warehouse": "_Test Warehouse - _TC", + "expense_account": "_Test Account Cost for Goods Sold - _TC", + "buying_cost_center": "_Test Cost Center - _TC", + "selling_cost_center": "_Test Cost Center - _TC", + "income_account": "Sales - _TC", + } + ], + }, + { + "description": "_Test Variant Item 12", + "doctype": "Item", + "has_batch_no": 0, + "has_serial_no": 0, + "inspection_required": 0, + "is_stock_item": 1, + "is_sub_contracted_item": 1, + "item_code": "_Test Variant Item", + "item_group": "_Test Item Group Desktops", + "item_name": "_Test Variant Item", + "stock_uom": "_Test UOM", + "has_variants": 1, + "item_defaults": [ + { + "company": "_Test Company", + "default_warehouse": "_Test Warehouse - _TC", + "expense_account": "_Test Account Cost for Goods Sold - _TC", + "buying_cost_center": "_Test Cost Center - _TC", + "selling_cost_center": "_Test Cost Center - _TC", + "income_account": "Sales - _TC", + } + ], + "attributes": [{"attribute": "Test Size"}], + "apply_warehouse_wise_reorder_level": 1, + "reorder_levels": [ + { + "material_request_type": "Purchase", + "warehouse": "_Test Warehouse - _TC", + "warehouse_reorder_level": 20, + "warehouse_reorder_qty": 20, + } + ], + }, + { + "description": "_Test Item 1", + "doctype": "Item", + "has_batch_no": 0, + "has_serial_no": 0, + "inspection_required": 0, + "is_stock_item": 1, + "is_sub_contracted_item": 0, + "item_code": "_Test Item Warehouse Group Wise Reorder", + "item_group": "_Test Item Group", + "item_name": "_Test Item Warehouse Group Wise Reorder", + "apply_warehouse_wise_reorder_level": 1, + "item_defaults": [ + { + "company": "_Test Company", + "default_warehouse": "_Test Warehouse Group-C1 - _TC", + "expense_account": "_Test Account Cost for Goods Sold - _TC", + "buying_cost_center": "_Test Cost Center - _TC", + "selling_cost_center": "_Test Cost Center - _TC", + "income_account": "Sales - _TC", + } + ], + "reorder_levels": [ + { + "warehouse_group": "_Test Warehouse Group - _TC", + "material_request_type": "Purchase", + "warehouse": "_Test Warehouse Group-C1 - _TC", + "warehouse_reorder_level": 20, + "warehouse_reorder_qty": 20, + } + ], + "stock_uom": "_Test UOM", + }, + { + "description": "_Test Item With Item Tax Template", + "doctype": "Item", + "has_batch_no": 0, + "has_serial_no": 0, + "inspection_required": 0, + "is_stock_item": 1, + "is_sub_contracted_item": 0, + "item_code": "_Test Item With Item Tax Template", + "item_group": "_Test Item Group", + "item_name": "_Test Item With Item Tax Template", + "stock_uom": "_Test UOM", + "item_defaults": [ + { + "company": "_Test Company", + "default_warehouse": "_Test Warehouse - _TC", + "expense_account": "_Test Account Cost for Goods Sold - _TC", + "buying_cost_center": "_Test Cost Center - _TC", + "selling_cost_center": "_Test Cost Center - _TC", + "income_account": "Sales - _TC", + } + ], + "taxes": [ + { + "doctype": "Item Tax", + "parentfield": "taxes", + "item_tax_template": "_Test Account Excise Duty @ 10 - _TC", + }, + { + "doctype": "Item Tax", + "parentfield": "taxes", + "item_tax_template": "_Test Account Excise Duty @ 12 - _TC", + "tax_category": "_Test Tax Category 1", + }, + ], + }, + { + "description": "_Test Item Inherit Group Item Tax Template 1", + "doctype": "Item", + "has_batch_no": 0, + "has_serial_no": 0, + "inspection_required": 0, + "is_stock_item": 1, + "is_sub_contracted_item": 0, + "item_code": "_Test Item Inherit Group Item Tax Template 1", + "item_group": "_Test Item Group Tax Parent", + "item_name": "_Test Item Inherit Group Item Tax Template 1", + "stock_uom": "_Test UOM", + "item_defaults": [ + { + "company": "_Test Company", + "default_warehouse": "_Test Warehouse - _TC", + "expense_account": "_Test Account Cost for Goods Sold - _TC", + "buying_cost_center": "_Test Cost Center - _TC", + "selling_cost_center": "_Test Cost Center - _TC", + "income_account": "Sales - _TC", + } + ], + }, + { + "description": "_Test Item Inherit Group Item Tax Template 2", + "doctype": "Item", + "has_batch_no": 0, + "has_serial_no": 0, + "inspection_required": 0, + "is_stock_item": 1, + "is_sub_contracted_item": 0, + "item_code": "_Test Item Inherit Group Item Tax Template 2", + "item_group": "_Test Item Group Tax Child Override", + "item_name": "_Test Item Inherit Group Item Tax Template 2", + "stock_uom": "_Test UOM", + "item_defaults": [ + { + "company": "_Test Company", + "default_warehouse": "_Test Warehouse - _TC", + "expense_account": "_Test Account Cost for Goods Sold - _TC", + "buying_cost_center": "_Test Cost Center - _TC", + "selling_cost_center": "_Test Cost Center - _TC", + "income_account": "Sales - _TC", + } + ], + }, + { + "description": "_Test Item Override Group Item Tax Template", + "doctype": "Item", + "has_batch_no": 0, + "has_serial_no": 0, + "inspection_required": 0, + "is_stock_item": 1, + "is_sub_contracted_item": 0, + "item_code": "_Test Item Override Group Item Tax Template", + "item_group": "_Test Item Group Tax Child Override", + "item_name": "_Test Item Override Group Item Tax Template", + "stock_uom": "_Test UOM", + "item_defaults": [ + { + "company": "_Test Company", + "default_warehouse": "_Test Warehouse - _TC", + "expense_account": "_Test Account Cost for Goods Sold - _TC", + "buying_cost_center": "_Test Cost Center - _TC", + "selling_cost_center": "_Test Cost Center - _TC", + "income_account": "Sales - _TC", + } + ], + "taxes": [ + { + "doctype": "Item Tax", + "parentfield": "taxes", + "item_tax_template": "_Test Account Excise Duty @ 20 - _TC", + }, + { + "doctype": "Item Tax", + "parentfield": "taxes", + "tax_category": "_Test Tax Category 1", + "item_tax_template": "_Test Item Tax Template 1 - _TC", + }, + ], + }, + { + "description": "_Test", + "doctype": "Item", + "is_stock_item": 1, + "item_code": "138-CMS Shoe", + "item_group": "_Test Item Group", + "item_name": "138-CMS Shoe", + "stock_uom": "_Test UOM", + }, + { + "doctype": "Item", + "item_code": "Photocopier", + "item_name": "Photocopier", + "item_group": "All Item Groups", + "company": "_Test Company", + "is_fixed_asset": 1, + "is_stock_item": 0, + "asset_category": "Equipment", + "auto_create_assets": 1, + "asset_naming_series": "ABC.###", + "stock_uom": "_Test UOM", + }, + { + "doctype": "Item", + "item_code": "Loyal Item", + "item_name": "Loyal Item", + "item_group": "All Item Groups", + "company": "_Test Company", + "is_stock_item": 1, + "opening_stock": 100, + "valuation_rate": 10000, + "stock_uom": "_Test UOM", + }, + { + "doctype": "Item", + "item_code": "_Test Extra Item 1", + "item_name": "_Test Extra Item 1", + "item_group": "All Item Groups", + "company": "_Test Company", + "is_stock_item": 1, + "stock_uom": "_Test UOM", + }, + { + "doctype": "Item", + "item_code": "_Test Extra Item 2", + "item_name": "_Test Extra Item 2", + "item_group": "All Item Groups", + "company": "_Test Company", + "is_stock_item": 1, + "stock_uom": "_Test UOM", + }, + { + "doctype": "Item", + "item_code": "Stock-Reco-Serial-Item-1", + "item_name": "Stock-Reco-Serial-Item-1", + "is_stock_item": 1, + "item_group": "All Item Groups", + "stock_uom": "Nos", + "has_serial_no": 1, + "serial_no_series": "SRSI.#####", + }, + { + "doctype": "Item", + "item_code": "Stock-Reco-Serial-Item-2", + "item_name": "Stock-Reco-Serial-Item-2", + "is_stock_item": 1, + "item_group": "All Item Groups", + "stock_uom": "Nos", + "has_serial_no": 1, + "serial_no_series": "SRSII.#####", + }, + { + "doctype": "Item", + "item_code": "Stock-Reco-batch-Item-1", + "item_name": "Stock-Reco-batch-Item-1", + "is_stock_item": 1, + "item_group": "All Item Groups", + "stock_uom": "Nos", + "has_batch_no": 1, + "batch_number_series": "BASR.#####", + "create_new_batch": 1, + }, + { + "doctype": "Item", + "item_code": "Test Asset Item", + "item_name": "Test Asset Item", + "is_stock_item": 0, + "item_group": "All Item Groups", + "stock_uom": "Box", + "is_fixed_asset": 1, + "auto_create_assets": 1, + "asset_category": "Equipment", + "asset_naming_series": "ABC.###", + }, + { + "doctype": "Item", + "item_code": "Macbook Pro", + "item_name": "Macbook Pro", + "description": "Macbook Pro Retina Display", + "asset_category": "Computers", + "item_group": "All Item Groups", + "stock_uom": "Nos", + "is_stock_item": 0, + "is_fixed_asset": 1, + "auto_create_assets": 1, + "is_grouped_asset": 0, + "asset_naming_series": "ACC-ASS-.YYYY.-", + }, + { + "doctype": "Item", + "item_code": "_Test Stock Item", + "item_name": "Test Stock Item", + "is_stock_item": 1, + "item_group": "All Item Groups", + "stock_uom": "Nos", + }, + { + "doctype": "Item", + "item_code": "Consulting", + "item_name": "Consulting", + "is_stock_item": 0, + "item_group": "All Item Groups", + "stock_uom": "Nos", + "company": "_Test Company", + }, + ] + self.make_records(["item_code", "item_name"], records) + + def make_product_bundle(self): + from erpnext.selling.doctype.product_bundle.product_bundle import get_active_product_bundle + + if get_active_product_bundle("_Test Product Bundle Item"): + return + + frappe.get_doc( + { + "doctype": "Product Bundle", + "new_item_code": "_Test Product Bundle Item", + "items": [ + { + "doctype": "Product Bundle Item", + "item_code": "_Test Item", + "parentfield": "items", + "qty": 5.0, + }, + { + "doctype": "Product Bundle Item", + "item_code": "_Test Item Home Desktop 100", + "parentfield": "items", + "qty": 2.0, + }, + ], + } + ).insert().submit() + + def make_test_account(self): + records = [ + # [account_name, parent_account, is_group] + ["_Test Bank", "Bank Accounts", 0, "Bank", None], + ["_Test Bank USD", "Bank Accounts", 0, "Bank", "USD"], + ["_Test Bank EUR", "Bank Accounts", 0, "Bank", "EUR"], + ["_Test Cash", "Cash In Hand", 0, "Cash", None], + ["_Test Account Stock Expenses", "Direct Expenses", 1, None, None], + ["_Test Account Shipping Charges", "_Test Account Stock Expenses", 0, "Chargeable", None], + ["_Test Account Customs Duty", "_Test Account Stock Expenses", 0, "Tax", None], + ["_Test Account Insurance Charges", "_Test Account Stock Expenses", 0, "Chargeable", None], + ["_Test Account Stock Adjustment", "_Test Account Stock Expenses", 0, "Stock Adjustment", None], + ["_Test Employee Advance", "Current Liabilities", 0, None, None], + ["_Test Account Tax Assets", "Current Assets", 1, None, None], + ["_Test Account VAT", "_Test Account Tax Assets", 0, "Tax", None], + ["_Test Account Service Tax", "_Test Account Tax Assets", 0, "Tax", None], + ["_Test Account Reserves and Surplus", "Current Liabilities", 0, None, None], + ["_Test Account Cost for Goods Sold", "Expenses", 0, None, None], + ["_Test Account Excise Duty", "_Test Account Tax Assets", 0, "Tax", None], + ["_Test Account Education Cess", "_Test Account Tax Assets", 0, "Tax", None], + ["_Test Account S&H Education Cess", "_Test Account Tax Assets", 0, "Tax", None], + ["_Test Account CST", "Direct Expenses", 0, "Tax", None], + ["_Test Account Discount", "Direct Expenses", 0, None, None], + ["_Test Write Off", "Indirect Expenses", 0, None, None], + ["_Test Exchange Gain/Loss", "Indirect Expenses", 0, None, None], + ["_Test Account Sales", "Direct Income", 0, None, None], + # related to Account Inventory Integration + ["_Test Account Stock In Hand", "Current Assets", 0, None, None], + # fixed asset depreciation + ["_Test Fixed Asset", "Current Assets", 0, "Fixed Asset", None], + ["_Test Accumulated Depreciations", "Current Assets", 0, "Accumulated Depreciation", None], + ["_Test Depreciations", "Expenses", 0, "Depreciation", None], + ["_Test Gain/Loss on Asset Disposal", "Expenses", 0, None, None], + # Receivable / Payable Account + ["_Test Receivable", "Current Assets", 0, "Receivable", None], + ["_Test Payable", "Current Liabilities", 0, "Payable", None], + ["_Test Receivable USD", "Current Assets", 0, "Receivable", "USD"], + ["_Test Payable USD", "Current Liabilities", 0, "Payable", "USD"], + # Deferred Account + ["Deferred Revenue", "Current Liabilities", 0, None, None], + ["Deferred Expense", "Current Assets", 0, None, None], + # Bank + ["HDFC", "Bank Accounts", 0, "Bank", None], + # Advance Account + ["Advance Received", "Current Liabilities", 0, "Receivable", None], + ["Advance Paid", "Current Assets", 0, "Payable", None], + # Loyalty Account + ["Loyalty", "Direct Expenses", 0, "Expense Account", None], + ] + + self.test_accounts = [] + for company, abbr in [ + ["_Test Company", "_TC"], + ["_Test Company 1", "_TC1"], + ["_Test Company with perpetual inventory", "TCP1"], + ]: + for account_name, parent_account, is_group, account_type, currency in records: + if not frappe.db.exists("Account", {"account_name": account_name, "company": company}): + self.test_accounts.append( + frappe.get_doc( + { + "doctype": "Account", + "account_name": account_name, + "parent_account": parent_account + " - " + abbr, + "company": company, + "is_group": is_group, + "account_type": account_type, + "account_currency": currency, + } + ).insert() + ) + else: + self.test_accounts.append( + frappe.get_doc("Account", {"account_name": account_name, "company": company}) + ) + + def make_customer(self): + records = [ + { + "customer_group": "_Test Customer Group", + "customer_name": "_Test Customer With Template", + "customer_type": "Individual", + "doctype": "Customer", + "territory": "_Test Territory", + }, + { + "customer_group": "_Test Customer Group", + "customer_name": "_Test Customer P", + "customer_type": "Individual", + "doctype": "Customer", + "territory": "_Test Territory", + }, + { + "customer_group": "_Test Customer Group", + "customer_name": "_Test Customer", + "customer_type": "Individual", + "doctype": "Customer", + "territory": "_Test Territory", + }, + { + "customer_group": "_Test Customer Group", + "customer_name": "_Test Customer 1", + "customer_type": "Individual", + "doctype": "Customer", + "territory": "_Test Territory", + }, + { + "customer_group": "_Test Customer Group", + "customer_name": "_Test Customer 2", + "customer_type": "Individual", + "doctype": "Customer", + "territory": "_Test Territory", + }, + { + "customer_group": "_Test Customer Group", + "customer_name": "_Test Customer 3", + "customer_type": "Individual", + "doctype": "Customer", + "territory": "_Test Territory", + }, + { + "customer_group": "_Test Customer Group", + "customer_name": "_Test Customer USD", + "customer_type": "Individual", + "doctype": "Customer", + "territory": "_Test Territory", + "default_currency": "USD", + "accounts": [{"company": "_Test Company", "account": "_Test Receivable USD - _TC"}], + }, + { + "customer_group": "_Test Customer Group", + "customer_name": "_Test Customer With Tax Category", + "customer_type": "Individual", + "doctype": "Customer", + "territory": "_Test Territory", + "tax_category": "_Test Tax Category 1", + }, + { + "customer_group": "_Test Customer Group", + "customer_name": "Test Loyalty Customer", + "customer_type": "Individual", + "doctype": "Customer", + "territory": "_Test Territory", + }, + { + "customer_group": "_Test Customer Group", + "customer_name": "_Test Internal Customer 2", + "customer_type": "Individual", + "doctype": "Customer", + "is_internal_customer": 1, + "territory": "_Test Territory", + "represents_company": "_Test Company with perpetual inventory", + "companies": [{"company": "_Test Company with perpetual inventory"}], + }, + { + "customer_group": "_Test Customer Group", + "customer_name": "Prestiga-Biz", + "customer_type": "Company", + "doctype": "Customer", + "territory": "_Test Territory", + }, + { + "customer_group": "_Test Customer Group", + "customer_name": "_Test NC", + "customer_type": "Individual", + "doctype": "Customer", + "territory": "_Test Territory", + }, + ] + self.make_records(["customer_name"], records) + + def make_shareholder(self): + records = [ + { + "doctype": "Shareholder", + "naming_series": "SH-", + "title": "Iron Man", + "company": "_Test Company", + }, + {"doctype": "Shareholder", "naming_series": "SH-", "title": "Thor", "company": "_Test Company"}, + {"doctype": "Shareholder", "naming_series": "SH-", "title": "Hulk", "company": "_Test Company"}, + ] + self.make_records(["title", "company"], records) + + def make_sales_taxes_template(self): + records = [ + { + "company": "_Test Company", + "doctype": "Sales Taxes and Charges Template", + "taxes": [ + { + "account_head": "_Test Account VAT - _TC", + "charge_type": "On Net Total", + "description": "VAT", + "doctype": "Sales Taxes and Charges", + "cost_center": "Main - _TC", + "parentfield": "taxes", + "rate": 6, + }, + { + "account_head": "_Test Account Service Tax - _TC", + "charge_type": "On Net Total", + "description": "Service Tax", + "doctype": "Sales Taxes and Charges", + "cost_center": "Main - _TC", + "parentfield": "taxes", + "rate": 6.36, + }, + ], + "title": "_Test Sales Taxes and Charges Template", + }, + { + "company": "_Test Company", + "doctype": "Sales Taxes and Charges Template", + "taxes": [ + { + "account_head": "_Test Account Shipping Charges - _TC", + "charge_type": "Actual", + "cost_center": "_Test Cost Center - _TC", + "description": "Shipping Charges", + "doctype": "Sales Taxes and Charges", + "parentfield": "taxes", + "tax_amount": 100, + }, + { + "account_head": "_Test Account Customs Duty - _TC", + "charge_type": "On Net Total", + "cost_center": "_Test Cost Center - _TC", + "description": "Customs Duty", + "doctype": "Sales Taxes and Charges", + "parentfield": "taxes", + "rate": 10, + }, + { + "account_head": "_Test Account Excise Duty - _TC", + "charge_type": "On Net Total", + "cost_center": "_Test Cost Center - _TC", + "description": "Excise Duty", + "doctype": "Sales Taxes and Charges", + "parentfield": "taxes", + "rate": 12, + }, + { + "account_head": "_Test Account Education Cess - _TC", + "charge_type": "On Previous Row Amount", + "cost_center": "_Test Cost Center - _TC", + "description": "Education Cess", + "doctype": "Sales Taxes and Charges", + "parentfield": "taxes", + "rate": 2, + "row_id": 3, + }, + { + "account_head": "_Test Account S&H Education Cess - _TC", + "charge_type": "On Previous Row Amount", + "cost_center": "_Test Cost Center - _TC", + "description": "S&H Education Cess", + "doctype": "Sales Taxes and Charges", + "parentfield": "taxes", + "rate": 1, + "row_id": 3, + }, + { + "account_head": "_Test Account CST - _TC", + "charge_type": "On Previous Row Total", + "cost_center": "_Test Cost Center - _TC", + "description": "CST", + "doctype": "Sales Taxes and Charges", + "parentfield": "taxes", + "rate": 2, + "row_id": 5, + }, + { + "account_head": "_Test Account VAT - _TC", + "charge_type": "On Net Total", + "cost_center": "_Test Cost Center - _TC", + "description": "VAT", + "doctype": "Sales Taxes and Charges", + "parentfield": "taxes", + "rate": 12.5, + }, + { + "account_head": "_Test Account Discount - _TC", + "charge_type": "On Previous Row Total", + "cost_center": "_Test Cost Center - _TC", + "description": "Discount", + "doctype": "Sales Taxes and Charges", + "parentfield": "taxes", + "rate": -10, + "row_id": 7, + }, + ], + "title": "_Test India Tax Master", + }, + { + "company": "_Test Company", + "doctype": "Sales Taxes and Charges Template", + "taxes": [ + { + "account_head": "_Test Account VAT - _TC", + "charge_type": "On Net Total", + "description": "VAT", + "doctype": "Sales Taxes and Charges", + "cost_center": "Main - _TC", + "parentfield": "taxes", + "rate": 12, + }, + { + "account_head": "_Test Account Service Tax - _TC", + "charge_type": "On Net Total", + "description": "Service Tax", + "doctype": "Sales Taxes and Charges", + "cost_center": "Main - _TC", + "parentfield": "taxes", + "rate": 4, + }, + ], + "title": "_Test Sales Taxes and Charges Template - Rest of the World", + }, + { + "company": "_Test Company", + "doctype": "Sales Taxes and Charges Template", + "taxes": [ + { + "account_head": "_Test Account VAT - _TC", + "charge_type": "On Net Total", + "description": "VAT", + "doctype": "Sales Taxes and Charges", + "cost_center": "Main - _TC", + "parentfield": "taxes", + "rate": 12, + }, + { + "account_head": "_Test Account Service Tax - _TC", + "charge_type": "On Net Total", + "description": "Service Tax", + "doctype": "Sales Taxes and Charges", + "cost_center": "Main - _TC", + "parentfield": "taxes", + "rate": 4, + }, + ], + "title": "_Test Sales Taxes and Charges Template 1", + }, + { + "company": "_Test Company", + "doctype": "Sales Taxes and Charges Template", + "taxes": [ + { + "account_head": "_Test Account VAT - _TC", + "charge_type": "On Net Total", + "description": "VAT", + "doctype": "Sales Taxes and Charges", + "cost_center": "Main - _TC", + "parentfield": "taxes", + "rate": 12, + }, + { + "account_head": "_Test Account Service Tax - _TC", + "charge_type": "On Net Total", + "description": "Service Tax", + "doctype": "Sales Taxes and Charges", + "cost_center": "Main - _TC", + "parentfield": "taxes", + "rate": 4, + }, + ], + "title": "_Test Sales Taxes and Charges Template 2", + }, + { + "doctype": "Sales Taxes and Charges Template", + "title": "_Test Tax 1", + "company": "_Test Company", + "taxes": [ + { + "charge_type": "Actual", + "account_head": "Sales Expenses - _TC", + "cost_center": "Main - _TC", + "description": "Test Shopping cart taxes with Tax Rule", + "tax_amount": 1000, + } + ], + }, + { + "doctype": "Sales Taxes and Charges Template", + "title": "_Test Tax 2", + "company": "_Test Company", + "taxes": [ + { + "charge_type": "Actual", + "account_head": "Sales Expenses - _TC", + "cost_center": "Main - _TC", + "description": "Test Shopping cart taxes with Tax Rule", + "tax_amount": 200, + } + ], + }, + ] + self.make_records(["title", "company"], records) + + def make_asset_category(self): + records = [ + { + "doctype": "Asset Category", + "asset_category_name": "Equipment", + "total_number_of_depreciations": 3, + "frequency_of_depreciation": 3, + "accounts": [ + { + "company_name": "_Test Company", + "fixed_asset_account": "_Test Fixed Asset - _TC", + "accumulated_depreciation_account": "_Test Accumulated Depreciations - _TC", + "depreciation_expense_account": "_Test Depreciations - _TC", + } + ], + }, + { + "doctype": "Asset Category", + "asset_category_name": "Computers", + "total_number_of_depreciations": 3, + "frequency_of_depreciation": 3, + "enable_cwip_accounting": True, + "accounts": [ + { + "company_name": "_Test Company", + "fixed_asset_account": "_Test Fixed Asset - _TC", + "accumulated_depreciation_account": "_Test Accumulated Depreciations - _TC", + "depreciation_expense_account": "_Test Depreciations - _TC", + "capital_work_in_progress_account": "CWIP Account - _TC", + }, + { + "company_name": "_Test Company with perpetual inventory", + "fixed_asset_account": "_Test Fixed Asset - TCP1", + "accumulated_depreciation_account": "_Test Accumulated Depreciations - TCP1", + "depreciation_expense_account": "_Test Depreciations - TCP1", + }, + ], + }, + ] + self.make_records(["asset_category_name"], records) + + def make_asset_maintenance_team(self): + records = [ + { + "doctype": "Asset Maintenance Team", + "maintenance_manager": "marcus@abc.com", + "maintenance_team_name": "Team Awesome", + "company": "_Test Company", + "maintenance_team_members": [ + { + "team_member": "marcus@abc.com", + "full_name": "marcus@abc.com", + "maintenance_role": "Technician", + }, + { + "team_member": "thalia@abc.com", + "full_name": "thalia@abc.com", + "maintenance_role": "Technician", + }, + { + "team_member": "mathias@abc.com", + "full_name": "mathias@abc.com", + "maintenance_role": "Technician", + }, + ], + } + ] + self.make_records(["maintenance_team_name"], records) + + def make_activity_type(self): + records = [ + { + "doctype": "Activity Type", + "name": "_Test Activity Type", + "activity_type": "_Test Activity Type", + }, + { + "doctype": "Activity Type", + "name": "_Test Activity Type 1", + "activity_type": "_Test Activity Type 1", + }, + ] + self.make_records(["activity_type"], records) + + def make_loyalty_program(self): + records = [ + { + "doctype": "Loyalty Program", + "loyalty_program_name": "Test Single Loyalty", + "auto_opt_in": 1, + "from_date": today(), + "loyalty_program_type": "Single Tier Program", + "conversion_factor": 1, + "expiry_duration": 10, + "company": "_Test Company", + "cost_center": "Main - _TC", + "expense_account": "Loyalty - _TC", + "collection_rules": [{"tier_name": "Bronce", "collection_factor": 1000, "min_spent": 0}], + }, + { + "doctype": "Loyalty Program", + "loyalty_program_name": "Test Multiple Loyalty", + "auto_opt_in": 1, + "from_date": today(), + "loyalty_program_type": "Multiple Tier Program", + "conversion_factor": 1, + "expiry_duration": 10, + "company": "_Test Company", + "cost_center": "Main - _TC", + "expense_account": "Loyalty - _TC", + "collection_rules": [ + {"tier_name": "Bronze", "collection_factor": 1000, "min_spent": 0}, + {"tier_name": "Silver", "collection_factor": 1000, "min_spent": 10000}, + {"tier_name": "Gold", "collection_factor": 1000, "min_spent": 19000}, + ], + }, + ] + self.make_records(["loyalty_program_name"], records) + + def make_item_price(self): + records = [ + { + "doctype": "Item Price", + "item_code": "_Test Item", + "price_list": "_Test Price List", + "price_list_rate": 100, + "valid_from": "2017-04-18", + "valid_upto": "2017-04-26", + }, + { + "doctype": "Item Price", + "item_code": "_Test Item", + "price_list": "_Test Price List Rest of the World", + "price_list_rate": 10, + }, + { + "doctype": "Item Price", + "item_code": "_Test Item 2", + "price_list": "_Test Price List Rest of the World", + "price_list_rate": 20, + "valid_from": "2017-04-18", + "valid_upto": "2017-04-26", + "customer": "_Test Customer", + "uom": "_Test UOM", + }, + { + "doctype": "Item Price", + "item_code": "_Test Item Home Desktop 100", + "price_list": "_Test Price List", + "price_list_rate": 1000, + "valid_from": "2017-04-10", + "valid_upto": "2017-04-17", + }, + { + "doctype": "Item Price", + "item_code": "_Test Item Home Desktop Manufactured", + "price_list": "_Test Price List", + "price_list_rate": 1000, + "valid_from": "2017-04-10", + "valid_upto": "2017-04-17", + }, + { + "doctype": "Item Price", + "item_code": "_Test Item", + "price_list": "_Test Buying Price List", + "price_list_rate": 100, + "supplier": "_Test Supplier", + }, + { + "doctype": "Item Price", + "item_code": "_Test Item", + "price_list": "_Test Selling Price List", + "price_list_rate": 200, + "customer": "_Test Customer", + }, + { + "doctype": "Item Price", + "price_list": _("Standard Selling"), + "item_code": "Loyal Item", + "price_list_rate": 10000, + }, + { + "doctype": "Item Price", + "item_code": "Consulting", + "price_list": "Standard Selling", + "price_list_rate": 10000, + }, + ] + self.make_records(["item_code", "price_list", "price_list_rate"], records) + + def make_operation(self): + records = [ + {"doctype": "Operation", "name": "_Test Operation 1", "workstation": "_Test Workstation 1"} + ] + self.make_records(["name"], records) + + def make_workstation(self): + records = [ + { + "doctype": "Workstation", + "name": "_Test Workstation 1", + "workstation_name": "_Test Workstation 1", + "warehouse": "_Test Warehouse - _TC", + "hour_rate_labour": 25, + "hour_rate_electricity": 25, + "hour_rate_consumable": 25, + "hour_rate_rent": 25, + "holiday_list": "_Test Holiday List", + "working_hours": [{"start_time": "10:00:00", "end_time": "20:00:00"}], + } + ] + self.make_records(["workstation_name"], records) + + def make_bom(self): + # TODO: replace JSON source with hardcoded data + records = load_test_records_for("BOM")["BOM"] + self.make_records(["item", "company"], records) + + def make_quality_inspection_param(self): + records = [{"doctype": "Quality Inspection Parameter", "parameter": "_Test Param"}] + self.make_records(["parameter"], records) + + def make_quality_inspection_template(self): + records = [ + { + "quality_inspection_template_name": "_Test Quality Inspection Template", + "doctype": "Quality Inspection Template", + "item_quality_inspection_parameter": [ + { + "specification": "_Test Param", + "doctype": "Item Quality Inspection Parameter", + "parentfield": "item_quality_inspection_parameter", + } + ], + } + ] + self.make_records(["quality_inspection_template_name"], records) + + def make_brand(self): + records = [ + {"brand": "_Test Brand", "doctype": "Brand"}, + { + "brand": "_Test Brand With Item Defaults", + "doctype": "Brand", + "brand_defaults": [ + { + "company": "_Test Company", + "expense_account": "_Test Account Cost for Goods Sold - _TC", + "income_account": "_Test Account Sales - _TC", + "buying_cost_center": "_Test Cost Center - _TC", + "selling_cost_center": "_Test Cost Center - _TC", + } + ], + }, + ] + self.make_records(["brand"], records) + + def make_dunning_type(self): + records = [ + { + "doctype": "Dunning Type", + "dunning_type": "First Notice", + "company": "_Test Company", + "is_default": 1, + "dunning_fee": 0, + "rate_of_interest": 0, + "income_account": "Sales - _TC", + "cost_center": "Main - _TC", + "dunning_letter_text": [ + { + "language": "en", + "body_text": "We have still not received payment for our invoice", + "closing_text": "We kindly request that you pay the outstanding amount immediately, including interest and late fees.", + }, + ], + }, + { + "doctype": "Dunning Type", + "dunning_type": "Second Notice", + "company": "_Test Company", + "is_default": 0, + "dunning_fee": 10, + "rate_of_interest": 10, + "income_account": "Sales - _TC", + "cost_center": "Main - _TC", + "dunning_letter_text": [ + { + "language": "en", + "body_text": "We have still not received payment for our invoice", + "closing_text": "We kindly request that you pay the outstanding amount immediately, including interest and late fees.", + }, + ], + }, + ] + self.make_records(["dunning_type"], records) + + def make_finance_book(self): + records = [ + { + "doctype": "Finance Book", + "finance_book_name": "Test Finance Book 1", + }, + { + "doctype": "Finance Book", + "finance_book_name": "Test Finance Book 2", + }, + { + "doctype": "Finance Book", + "finance_book_name": "Test Finance Book 3", + }, + ] + self.make_records(["finance_book_name"], records) + + def make_custom_doctype(self): + if not frappe.db.exists("DocType", "Shelf"): + frappe.get_doc( + { + "doctype": "DocType", + "name": "Shelf", + "module": "Stock", + "custom": 1, + "naming_rule": "By fieldname", + "autoname": "field:shelf_name", + "fields": [{"label": "Shelf Name", "fieldname": "shelf_name", "fieldtype": "Data"}], + "permissions": [ + { + "role": "System Manager", + "permlevel": 0, + "read": 1, + "write": 1, + "create": 1, + "delete": 1, + } + ], + } + ).insert(ignore_permissions=True) + + if not frappe.db.exists("DocType", "Rack"): + frappe.get_doc( + { + "doctype": "DocType", + "name": "Rack", + "module": "Stock", + "custom": 1, + "naming_rule": "By fieldname", + "autoname": "field:rack_name", + "fields": [{"label": "Rack Name", "fieldname": "rack_name", "fieldtype": "Data"}], + "permissions": [ + { + "role": "System Manager", + "permlevel": 0, + "read": 1, + "write": 1, + "create": 1, + "delete": 1, + } + ], + } + ).insert(ignore_permissions=True) + + if not frappe.db.exists("DocType", "Pallet"): + frappe.get_doc( + { + "doctype": "DocType", + "name": "Pallet", + "module": "Stock", + "custom": 1, + "naming_rule": "By fieldname", + "autoname": "field:pallet_name", + "fields": [{"label": "Pallet Name", "fieldname": "pallet_name", "fieldtype": "Data"}], + "permissions": [ + { + "role": "System Manager", + "permlevel": 0, + "read": 1, + "write": 1, + "create": 1, + "delete": 1, + } + ], + } + ).insert(ignore_permissions=True) + + if not frappe.db.exists("DocType", "Inv Site"): + frappe.get_doc( + { + "doctype": "DocType", + "name": "Inv Site", + "module": "Stock", + "custom": 1, + "naming_rule": "By fieldname", + "autoname": "field:site_name", + "fields": [{"label": "Site Name", "fieldname": "site_name", "fieldtype": "Data"}], + "permissions": [ + { + "role": "System Manager", + "permlevel": 0, + "read": 1, + "write": 1, + "create": 1, + "delete": 1, + } + ], + } + ).insert(ignore_permissions=True) + + if not frappe.db.exists("DocType", "Store"): + frappe.get_doc( + { + "doctype": "DocType", + "name": "Store", + "module": "Stock", + "custom": 1, + "naming_rule": "By fieldname", + "autoname": "field:store_name", + "fields": [{"label": "Store Name", "fieldname": "store_name", "fieldtype": "Data"}], + "permissions": [ + { + "role": "System Manager", + "permlevel": 0, + "read": 1, + "write": 1, + "create": 1, + "delete": 1, + } + ], + } + ).insert(ignore_permissions=True) + + if not frappe.db.exists("DocType", "Order Assignment"): + frappe.get_doc( + { + "doctype": "DocType", + "name": "Order Assignment", + "module": "Buying", + "custom": 1, + "autoname": "field:po", + "fields": [ + { + "label": "PO", + "fieldname": "po", + "fieldtype": "Link", + "options": "Purchase Order", + }, + { + "label": "Supplier", + "fieldname": "supplier", + "fieldtype": "Data", + "fetch_from": "po.supplier", + }, + ], + "permissions": [ + { + "create": 1, + "delete": 1, + "email": 1, + "export": 1, + "print": 1, + "read": 1, + "report": 1, + "role": "System Manager", + "share": 1, + "write": 1, + }, + {"read": 1, "role": "Supplier"}, + ], + } + ).insert(ignore_if_duplicate=True) + + def make_address(self): + records = [ + { + "doctype": "Address", + "address_type": "Billing", + "address_line1": "Address line 1", + "address_title": "_Test Billing Address Title", + "city": "Lagos", + "country": "Nigeria", + "links": [ + {"link_doctype": "Customer", "link_name": "_Test Customer 2", "doctype": "Dynamic Link"} + ], + }, + { + "doctype": "Address", + "address_type": "Shipping", + "address_line1": "Address line 2", + "address_title": "_Test Shipping Address 1 Title", + "city": "Lagos", + "country": "Nigeria", + "links": [ + {"link_doctype": "Customer", "link_name": "_Test Customer 2", "doctype": "Dynamic Link"} + ], + }, + { + "doctype": "Address", + "address_type": "Shipping", + "address_line1": "Address line 3", + "address_title": "_Test Shipping Address 2 Title", + "city": "Lagos", + "country": "Nigeria", + "is_shipping_address": "1", + "links": [ + {"link_doctype": "Customer", "link_name": "_Test Customer 2", "doctype": "Dynamic Link"} + ], + }, + { + "doctype": "Address", + "address_type": "Billing", + "address_line1": "Address line 4", + "address_title": "_Test Billing Address 2 Title", + "city": "Lagos", + "country": "Nigeria", + "is_shipping_address": "1", + "links": [ + {"link_doctype": "Customer", "link_name": "_Test Customer 1", "doctype": "Dynamic Link"} + ], + }, + { + "doctype": "Address", + "address_title": "_Test Address for Customer", + "address_type": "Office", + "address_line1": "Station Road", + "city": "_Test City", + "state": "Test State", + "country": "India", + "links": [{"link_doctype": "Customer", "link_name": "_Test Customer"}], + }, + ] + self.make_records(["address_title", "address_type"], records) + + def make_contact(self): + records = [ + { + "doctype": "Contact", + "first_name": "_Test Contact for _Test Customer", + "email_ids": [{"email_id": "test_contact_customer@example.com", "is_primary": True}], + "phone_nos": [{"phone": "+91 0000000000", "is_primary_phone": True}], + "links": [{"link_doctype": "Customer", "link_name": "_Test Customer"}], + }, + { + "doctype": "Contact", + "first_name": "_Test Contact 2 for _Test Customer", + "email_ids": [{"email_id": "test_contact_two_customer@example.com", "is_primary": True}], + "phone_nos": [{"phone": "+92 0000000000", "is_primary_phone": True}], + "links": [{"link_doctype": "Customer", "link_name": "_Test Customer"}], + }, + ] + self.make_records(["first_name"], records) + + def make_dimensions(self): + records = [ + { + "doctype": "Accounting Dimension", + "document_type": "Department", + "dimension_defaults": [ + { + "company": "_Test Company", + "reference_document": "Department", + "default_dimension": "_Test Department - _TC", + } + ], + }, + { + "doctype": "Accounting Dimension", + "document_type": "Location", + "dimension_defaults": [ + { + "company": "_Test Company", + "reference_document": "Location", + "default_dimension": "Block 1", + } + ], + }, + { + "doctype": "Accounting Dimension", + "document_type": "Branch", + }, + ] + self.make_records(["document_type"], records) + + def make_custom_field(self): + pan_field = { + "Supplier": [ + { + "fieldname": "pan", + "label": "PAN", + "fieldtype": "Data", + "translatable": 0, + } + ] + } + + create_custom_fields(pan_field, update=1) + + def make_shelf(self): + records = [ + { + "doctype": "Shelf", + "shelf_name": "Shelf 1", + }, + { + "doctype": "Shelf", + "shelf_name": "Shelf 2", + }, + ] + self.make_records(["shelf_name"], records) + + def make_rack(self): + records = [ + { + "doctype": "Rack", + "rack_name": "Rack 1", + }, + { + "doctype": "Rack", + "rack_name": "Rack 2", + }, + ] + self.make_records(["rack_name"], records) + + def make_inv_site(self): + records = [ + { + "doctype": "Inv Site", + "site_name": "Site 1", + }, + { + "doctype": "Inv Site", + "site_name": "Site 2", + }, + ] + self.make_records(["site_name"], records) + + def make_store(self): + records = [ + { + "doctype": "Store", + "store_name": "Store 1", + }, + { + "doctype": "Store", + "store_name": "Store 2", + }, + ] + self.make_records(["store_name"], records) + + +BootStrapTestData() + + +class ERPNextTestSuite(unittest.TestCase): + @classmethod + def registerAs(cls, _as): + def decorator(cm_func): + setattr(cls, cm_func.__name__, _as(cm_func)) + return cm_func + + return decorator + + @classmethod + def setUpClass(cls): + cls.globalTestRecords = {} + + def tearDown(self): + frappe.db.rollback() + frappe.local.request_cache.clear() + if hasattr(frappe.local, "future_sle"): + frappe.local.future_sle.clear() + + def load_test_records(self, doctype): + if doctype not in self.globalTestRecords: + records = load_test_records_for(doctype) + self.globalTestRecords[doctype] = records[doctype] + + @contextmanager + def set_user(self, user: str): + try: + old_user = frappe.session.user + frappe.set_user(user) + yield + finally: + frappe.set_user(old_user) + + +@ERPNextTestSuite.registerAs(staticmethod) +@contextmanager +def change_settings(doctype, settings_dict=None, /, **settings) -> None: + """Temporarily: change settings in a settings doctype.""" + import copy + + if settings_dict is None: + settings_dict = settings + + settings = frappe.get_doc(doctype) + previous_settings = copy.deepcopy(settings_dict) + for key in previous_settings: + previous_settings[key] = getattr(settings, key) + + for key, value in settings_dict.items(): + setattr(settings, key, value) + settings.save(ignore_permissions=True) + + yield + + settings = frappe.get_doc(doctype) + for key, value in previous_settings.items(): + setattr(settings, key, value) + settings.save(ignore_permissions=True) +>>>>>>> 8a940af7e1 (fix: added permission checks on various whitelisted functions (#56745))