resilient-tech / india-compliance

Simple, yet powerful compliance solutions for Indian businesses
https://indiacompliance.app
GNU General Public License v3.0
142 stars 127 forks source link

bench update/migrate failing due to patch india_compliance.patches.v15.migrate_print_options_to_new_field #2335

Closed melgo-tb closed 2 months ago

melgo-tb commented 2 months ago

Information about bug

Error when running migrate to run patches. Command ran bench update --reset --no-backup && bench setup requirements && bench build or bench --site est.localhost migrate

Version

erpnext 15.28.2 frappe 15.32.0 hrms 15.23.0 india_compliance 15.9.1

Relevant log output / Stack trace / Full Error Message.

frappe@81bf8ea000de:/workspace/development/kf-bench/apps/india_compliance$ bench --site est.localhost migrate
Migrating est.localhost
Updating DocTypes for frappe        : [========================================] 100%
Updating DocTypes for erpnext       : [========================================] 100%
Updating DocTypes for hrms          : [========================================] 100%
Updating DocTypes for payments      : [========================================] 100%
Updating DocTypes for india_compliance: [========================================] 100%
Updating DocTypes for kohinoor      : [========================================] 100%
Executing india_compliance.patches.v15.migrate_print_options_to_new_field in est.localhost (_2d7bf6bdfca4d0ae)
Queued rebuilding of search index for est.localhost

Traceback with variables (most recent call last):
  File "<frozen runpy>", line 198, in _run_module_as_main
      mod_name = 'frappe.utils.bench_helper'
      alter_argv = True
      mod_spec = ModuleSpec(name='frappe.utils.bench_helper', loader=<_frozen_importlib_external.SourceFileLoader object at 0x7f44e8256e90>, origin='/workspace/development/kf-bench/apps/frappe/frappe/utils/bench_helper.py')
      code = <code object <module> at 0x55aad7ca5750, file "/workspace/development/kf-bench/apps/frappe/frappe/utils/bench_helper.py", line 1>
      main_globals = {'__name__': '__main__', '__doc__': None, '__package__': 'frappe.utils', '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x7f44e8256e90>, '__spec__': ModuleSpec(name='frappe.utils.bench_helper', loader=<_frozen_importlib_external.SourceFileLoader object at 0x7f44e8256e90>, origin='/workspace/development/kf-bench/apps/frappe/frappe/utils/bench_helper.py'), '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, '__file__': '/workspace/development/kf-bench/apps/frappe/frappe/utils/bench_helper.py', '__cached__': '/workspace/development/kf-bench/apps/frappe/frappe/utils/__pycache__/bench_helper.cpython-311.pyc', 'importlib': <module 'importlib' from '/home/frappe/.pyenv/versions/3.11.6/lib/python3.11/importlib/__init__.py'>, 'json': <module 'json' from '/home/frappe/.pyenv/versions/3.11.6/lib/python3.11/json/__init__.py'>, 'os': <module 'os' (frozen)>, 'traceback': <module 'traceback' from '/home/frappe/.pyenv/versions/3.11.6/lib/python3.11/traceback.py...
  File "<frozen runpy>", line 88, in _run_code
      code = <code object <module> at 0x55aad7ca5750, file "/workspace/development/kf-bench/apps/frappe/frappe/utils/bench_helper.py", line 1>
      run_globals = {'__name__': '__main__', '__doc__': None, '__package__': 'frappe.utils', '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x7f44e8256e90>, '__spec__': ModuleSpec(name='frappe.utils.bench_helper', loader=<_frozen_importlib_external.SourceFileLoader object at 0x7f44e8256e90>, origin='/workspace/development/kf-bench/apps/frappe/frappe/utils/bench_helper.py'), '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, '__file__': '/workspace/development/kf-bench/apps/frappe/frappe/utils/bench_helper.py', '__cached__': '/workspace/development/kf-bench/apps/frappe/frappe/utils/__pycache__/bench_helper.cpython-311.pyc', 'importlib': <module 'importlib' from '/home/frappe/.pyenv/versions/3.11.6/lib/python3.11/importlib/__init__.py'>, 'json': <module 'json' from '/home/frappe/.pyenv/versions/3.11.6/lib/python3.11/json/__init__.py'>, 'os': <module 'os' (frozen)>, 'traceback': <module 'traceback' from '/home/frappe/.pyenv/versions/3.11.6/lib/python3.11/traceback.py...
      init_globals = None
      mod_name = '__main__'
      mod_spec = ModuleSpec(name='frappe.utils.bench_helper', loader=<_frozen_importlib_external.SourceFileLoader object at 0x7f44e8256e90>, origin='/workspace/development/kf-bench/apps/frappe/frappe/utils/bench_helper.py')
      pkg_name = 'frappe.utils'
      script_name = None
      loader = <_frozen_importlib_external.SourceFileLoader object at 0x7f44e8256e90>
      fname = '/workspace/development/kf-bench/apps/frappe/frappe/utils/bench_helper.py'
      cached = '/workspace/development/kf-bench/apps/frappe/frappe/utils/__pycache__/bench_helper.cpython-311.pyc'
  File "/workspace/development/kf-bench/apps/frappe/frappe/utils/bench_helper.py", line 114, in <module>
    main()
      ...skipped... 27 vars
  File "/workspace/development/kf-bench/apps/frappe/frappe/utils/bench_helper.py", line 20, in main
    click.Group(commands=commands)(prog_name="bench")
      commands = {'frappe': <Group frappe>, 'get-frappe-commands': <Command get-frappe-commands>, 'get-frappe-help': <Command get-frappe-help>}
  File "/workspace/development/kf-bench/env/lib/python3.11/site-packages/click/core.py", line 1157, in __call__
    return self.main(*args, **kwargs)
      self = <Group None>
      args = ()
      kwargs = {'prog_name': 'bench'}
  File "/workspace/development/kf-bench/env/lib/python3.11/site-packages/click/core.py", line 1078, in main
    rv = self.invoke(ctx)
      self = <Group None>
      args = ['frappe', '--site', 'est.localhost', 'migrate']
      prog_name = 'bench'
      complete_var = None
      standalone_mode = True
      windows_expand_args = True
      extra = {}
      ctx = <click.core.Context object at 0x7f44e6804890>
  File "/workspace/development/kf-bench/env/lib/python3.11/site-packages/click/core.py", line 1688, in invoke
    return _process_result(sub_ctx.command.invoke(sub_ctx))
      self = <Group None>
      ctx = <click.core.Context object at 0x7f44e6804890>
      _process_result = <function MultiCommand.invoke.<locals>._process_result at 0x7f44e6e45d00>
      args = ['migrate']
      cmd_name = 'frappe'
      cmd = <Group frappe>
      sub_ctx = <click.core.Context object at 0x7f44e7ef0e90>
      __class__ = <class 'click.core.MultiCommand'>
  File "/workspace/development/kf-bench/env/lib/python3.11/site-packages/click/core.py", line 1688, in invoke
    return _process_result(sub_ctx.command.invoke(sub_ctx))
      self = <Group frappe>
      ctx = <click.core.Context object at 0x7f44e7ef0e90>
      _process_result = <function MultiCommand.invoke.<locals>._process_result at 0x7f44e6e45b20>
      args = []
      cmd_name = 'migrate'
      cmd = <Command migrate>
      sub_ctx = <click.core.Context object at 0x7f44e6e42310>
      __class__ = <class 'click.core.MultiCommand'>
  File "/workspace/development/kf-bench/env/lib/python3.11/site-packages/click/core.py", line 1434, in invoke
    return ctx.invoke(self.callback, **ctx.params)
      self = <Command migrate>
      ctx = <click.core.Context object at 0x7f44e6e42310>
  File "/workspace/development/kf-bench/env/lib/python3.11/site-packages/click/core.py", line 783, in invoke
    return __callback(*args, **kwargs)
      _Context__self = <click.core.Context object at 0x7f44e6e42310>
      _Context__callback = <function migrate at 0x7f44e67bc040>
      args = ()
      kwargs = {'skip_failing': False, 'skip_search_index': False}
      ctx = <click.core.Context object at 0x7f44e6e42310>
  File "/workspace/development/kf-bench/env/lib/python3.11/site-packages/click/decorators.py", line 33, in new_func
    return f(get_current_context(), *args, **kwargs)
      args = ()
      kwargs = {'skip_failing': False, 'skip_search_index': False}
      f = <function migrate at 0x7f44e6793d80>
  File "/workspace/development/kf-bench/apps/frappe/frappe/commands/__init__.py", line 29, in _func
    ret = f(frappe._dict(ctx.obj), *args, **kwargs)
      ctx = <click.core.Context object at 0x7f44e6e42310>
      args = ()
      kwargs = {'skip_failing': False, 'skip_search_index': False}
      profile = False
      f = <function migrate at 0x7f44e6793ce0>
  File "/workspace/development/kf-bench/apps/frappe/frappe/commands/site.py", line 616, in migrate
    ).run(site=site)
      context = {'sites': ['est.localhost'], 'force': False, 'verbose': False, 'profile': False}
      skip_failing = False
      skip_search_index = False
      activate_by_import = <module 'traceback_with_variables.activate_by_import' from '/workspace/development/kf-bench/env/lib/python3.11/site-packages/traceback_with_variables/activate_by_import.py'>
      SiteMigration = <class 'frappe.migrate.SiteMigration'>
      site = 'est.localhost'
  File "/workspace/development/kf-bench/apps/frappe/frappe/migrate.py", line 186, in run
    self.run_schema_updates()
      self = <frappe.migrate.SiteMigration object at 0x7f44e47edd10>
      site = 'est.localhost'
      filelock = <function filelock at 0x7f44e4549620>
  File "/workspace/development/kf-bench/apps/frappe/frappe/migrate.py", line 52, in wrapper
    raise e
      args = (<frappe.migrate.SiteMigration object at 0x7f44e47edd10>,)
      kwargs = {}
      method = <function SiteMigration.run_schema_updates at 0x7f44e4548fe0>
  File "/workspace/development/kf-bench/apps/frappe/frappe/migrate.py", line 44, in wrapper
    ret = method(*args, **kwargs)
      args = (<frappe.migrate.SiteMigration object at 0x7f44e47edd10>,)
      kwargs = {}
      method = <function SiteMigration.run_schema_updates at 0x7f44e4548fe0>
  File "/workspace/development/kf-bench/apps/frappe/frappe/migrate.py", line 121, in run_schema_updates
    frappe.modules.patch_handler.run_all(
      self = <frappe.migrate.SiteMigration object at 0x7f44e47edd10>
  File "/workspace/development/kf-bench/apps/frappe/frappe/modules/patch_handler.py", line 76, in run_all
    run_patch(patch)
      skip_failing = False
      patch_type = <PatchType.post_model_sync: 'post_model_sync'>
      executed = {'erpnext.patches.v11_0.move_item_defaults_to_child_table_for_multicompany #02-07-2018 #19-06-2019', 'erpnext.patches.v13_0.rename_issue_doctype_fields', 'erpnext.patches.v13_0.bill_for_rejected_quantity_in_purchase_invoice', 'execute:from erpnext.stock.doctype.repost_item_valuation.repost_item_valuation import execute_repost_item_valuation; execute_repost_item_valuation()', 'erpnext.patches.v13_0.create_gst_payment_entry_fields #27-11-2021', 'execute:frappe.delete_doc_if_exists("Page", "sales-analytics")', 'erpnext.patches.v11_1.setup_guardian_role', 'erpnext.patches.v11_0.rename_overproduction_percent_field', 'erpnext.patches.v12_0.unset_customer_supplier_based_on_type_of_item_price', 'execute:from india_compliance.gst_india.setup import create_property_setters; create_property_setters() #3', 'erpnext.patches.v12_0.update_bom_in_so_mr', 'erpnext.patches.v10_1.transfer_subscription_to_auto_repeat', 'erpnext.patches.v13_0.set_youtube_video_id', 'erpnext.patches.v10_0.fichier_des_ecritu...
      run_patch = <function run_all.<locals>.run_patch at 0x7f44e3497740>
      patches = ["execute:frappe.get_doc('Role', 'Guest').save() # remove desk access", 'frappe.core.doctype.role.patches.v13_set_default_desk_properties', 'frappe.patches.v14_0.update_workspace2 # 06.06.2023', 'frappe.patches.v14_0.drop_data_import_legacy', 'frappe.patches.v14_0.copy_mail_data #08.03.21', 'frappe.patches.v14_0.update_github_endpoints #08-11-2021', 'frappe.patches.v14_0.remove_db_aggregation', 'frappe.patches.v14_0.update_color_names_in_kanban_board_column', 'frappe.patches.v14_0.update_is_system_generated_flag', 'frappe.patches.v14_0.update_auto_account_deletion_duration', 'frappe.patches.v14_0.update_integration_request', 'frappe.patches.v14_0.set_document_expiry_default', 'frappe.patches.v14_0.delete_data_migration_tool', 'frappe.patches.v14_0.set_suspend_email_queue_default', 'frappe.patches.v14_0.different_encryption_key', 'frappe.patches.v14_0.update_multistep_webforms', "execute:frappe.delete_doc('Page', 'background_jobs', ignore_missing=True, force=True)", 'frappe.patches.v14_...
      patch = 'india_compliance.patches.v15.migrate_print_options_to_new_field'
  File "/workspace/development/kf-bench/apps/frappe/frappe/modules/patch_handler.py", line 62, in run_patch
    if not run_single(patchmodule=patch):
      patch = 'india_compliance.patches.v15.migrate_print_options_to_new_field'
      skip_failing = False
  File "/workspace/development/kf-bench/apps/frappe/frappe/modules/patch_handler.py", line 152, in run_single
    return execute_patch(patchmodule, method, methodargs)
      patchmodule = 'india_compliance.patches.v15.migrate_print_options_to_new_field'
      method = None
      methodargs = None
      force = False
      conf = <LocalProxy unbound>
  File "/workspace/development/kf-bench/apps/frappe/frappe/modules/patch_handler.py", line 188, in execute_patch
    _patch()
      patchmodule = 'india_compliance.patches.v15.migrate_print_options_to_new_field'
      method = None
      methodargs = None
      has_patch_file = True
      patch = 'india_compliance.patches.v15.migrate_print_options_to_new_field.execute'
      docstring = ''
      _patch = <function execute at 0x7f44e33ecae0>
      start_time = 5369.480989631
  File "/workspace/development/kf-bench/apps/india_compliance/india_compliance/patches/v15/migrate_print_options_to_new_field.py", line 11, in execute
    .run()
      doc = Table('tabCompany Print Options')
  File "/workspace/development/kf-bench/apps/frappe/frappe/query_builder/utils.py", line 87, in execute_query
    result = frappe.db.sql(query, params, *args, **kwargs)  # nosemgrep
      query = 'UPDATE `tabCompany Print Options` SET `print_label`=`autofield`,`print_value`=`autofield_value`'
      args = ()
      kwargs = {}
      child_queries = []
      params = {}
      execute_child_queries = <function patch_query_execute.<locals>.execute_child_queries at 0x7f44e388bf60>
      prepare_query = <function patch_query_execute.<locals>.prepare_query at 0x7f44e388c040>
  File "/workspace/development/kf-bench/apps/frappe/frappe/database/database.py", line 234, in sql
    self._cursor.execute(query, values)
      self = <frappe.database.mariadb.database.MariaDBDatabase object at 0x7f44e47fba50>
      query = 'UPDATE `tabCompany Print Options` SET `print_label`=`autofield`,`print_value`=`autofield_value`'
      values = {}
      as_dict = 0
      as_list = 0
      debug = False
      ignore_ddl = 0
      auto_commit = 0
      update = None
      explain = False
      run = True
      pluck = False
      as_iterator = False
      trace_id = None
  File "/workspace/development/kf-bench/env/lib/python3.11/site-packages/pymysql/cursors.py", line 153, in execute
    result = self._query(query)
      self = <pymysql.cursors.Cursor object at 0x7f44e480ef90>
      query = 'UPDATE `tabCompany Print Options` SET `print_label`=`autofield`,`print_value`=`autofield_value`'
      args = {}
  File "/workspace/development/kf-bench/env/lib/python3.11/site-packages/pymysql/cursors.py", line 322, in _query
    conn.query(q)
      self = <pymysql.cursors.Cursor object at 0x7f44e480ef90>
      q = 'UPDATE `tabCompany Print Options` SET `print_label`=`autofield`,`print_value`=`autofield_value`'
      conn = <pymysql.connections.Connection object at 0x7f44e47f3f90>
  File "/workspace/development/kf-bench/env/lib/python3.11/site-packages/pymysql/connections.py", line 563, in query
    self._affected_rows = self._read_query_result(unbuffered=unbuffered)
      self = <pymysql.connections.Connection object at 0x7f44e47f3f90>
      sql = b'UPDATE `tabCompany Print Options` SET `print_label`=`autofield`,`print_value`=`autofield_value`'
      unbuffered = False
  File "/workspace/development/kf-bench/env/lib/python3.11/site-packages/pymysql/connections.py", line 825, in _read_query_result
    result.read()
      self = <pymysql.connections.Connection object at 0x7f44e47f3f90>
      unbuffered = False
      result = <pymysql.connections.MySQLResult object at 0x7f44e3290610>
  File "/workspace/development/kf-bench/env/lib/python3.11/site-packages/pymysql/connections.py", line 1199, in read
    first_packet = self.connection._read_packet()
      self = <pymysql.connections.MySQLResult object at 0x7f44e3290610>
  File "/workspace/development/kf-bench/env/lib/python3.11/site-packages/pymysql/connections.py", line 775, in _read_packet
    packet.raise_for_error()
      self = <pymysql.connections.Connection object at 0x7f44e47f3f90>
      packet_type = <class 'pymysql.protocol.MysqlPacket'>
      buff = bytearray(b"\xff\x1e\x04#42S22Unknown column \'autofield\' in \'field list\'")
      packet_header = b'3\x00\x00\x01'
      btrl = 51
      btrh = 0
      packet_number = 1
      bytes_to_read = 51
      recv_data = b"\xff\x1e\x04#42S22Unknown column 'autofield' in 'field list'"
      packet = <pymysql.protocol.MysqlPacket object at 0x7f44e32f25c0>
  File "/workspace/development/kf-bench/env/lib/python3.11/site-packages/pymysql/protocol.py", line 219, in raise_for_error
    err.raise_mysql_exception(self._data)
      self = <pymysql.protocol.MysqlPacket object at 0x7f44e32f25c0>
      errno = 1054
  File "/workspace/development/kf-bench/env/lib/python3.11/site-packages/pymysql/err.py", line 150, in raise_mysql_exception
    raise errorclass(errno, errval)
      data = b"\xff\x1e\x04#42S22Unknown column 'autofield' in 'field list'"
      errno = 1054
      errval = "Unknown column 'autofield' in 'field list'"
      errorclass = <class 'pymysql.err.OperationalError'>
pymysql.err.OperationalError: (1054, "Unknown column 'autofield' in 'field list'")

Code of Conduct

Huly®: IC-2448

melgo-tb commented 2 months ago

Updating the patch to check for columns before setting them seems to have fixed the issue for me

import frappe

def execute():
    # Ensure the columns exist
    ensure_columns_exist()

    doc = frappe.qb.DocType("Company Print Options")

    (
        frappe.qb.update(doc)
        .set(doc.print_label, doc.autofield)
        .set(doc.print_value, doc.autofield_value)
        .run()
    )

def ensure_columns_exist():
    # Check if the 'autofield' column exists and add it if it doesn't
    if not frappe.db.has_column("Company Print Options", "autofield"):
        frappe.db.sql("""
            ALTER TABLE `tabCompany Print Options`
            ADD COLUMN `autofield` VARCHAR(255)
        """)

    # Check if the 'autofield_value' column exists and add it if it doesn't
    if not frappe.db.has_column("Company Print Options", "autofield_value"):
        frappe.db.sql("""
            ALTER TABLE `tabCompany Print Options`
            ADD COLUMN `autofield_value` VARCHAR(255)
        """)

# Run the patch
if __name__ == "__main__":
    execute()