'Set the record owned_by_user, owned_by_group and realm_entity
for a record (auto-detect values).
To be called by CRUD and Importer during record creation.
@param table: the Table (or table name)
@param record: the record (or record ID)
@param force_update: True to update all fields regardless of
the current value in the record, False
to only update if current value is None
@param fields: override auto-detected values, see keywords
@keyword owned_by_user: the auth_user ID of the owner user
@keyword owned_by_group: the auth_group ID of the owner group
@keyword realm_entity: the pe_id of the realm entity, or a tuple
(instance_type, instance_id) to lookup the
pe_id, e.g. ("org_organisation", 2)
@note: Only use with force_update for deliberate owner changes (i.e.
with explicit owned_by_user/owned_by_group) - autodetected
values can have undesirable side-effects. For mere realm
updates use set_realm_entity instead.
@note: If used with force_update, this will also update the
realm_entity in all configured realm_components, i.e.
no separate call to set_realm_entity required.'

def s3_set_record_owner(self, table, record, force_update=False, **fields):

    s3db = current.s3db
    OUSR = 'owned_by_user'
    OGRP = 'owned_by_group'
    REALM = 'realm_entity'
    ownership_fields = (OUSR, OGRP, REALM)
    EID = 'pe_id'
    OID = 'organisation_id'
    SID = 'site_id'
    GID = 'group_id'
    PID = 'person_id'
    entity_fields = (EID, OID, SID, GID, PID)
    if hasattr(table, '_tablename'):
        tablename = original_tablename(table)
    else:
        tablename = table
        table = s3db.table(tablename)
    if (not table):
        return
    pkey = table._id.name
    if isinstance(record, (Row, dict)):
        if (pkey not in record):
            return
        else:
            record_id = record[pkey]
    else:
        record_id = record
        record = Storage()
    fields_in_table = [f for f in ownership_fields if (f in table.fields)]
    if (not fields_in_table):
        return
    fields_in_table += [f for f in entity_fields if (f in table.fields)]
    fields_missing = [f for f in fields_in_table if (f not in record)]
    if fields_missing:
        fields_to_load = ([table._id] + [table[f] for f in fields_in_table])
        query = (table._id == record_id)
        row = current.db(query).select(limitby=(0, 1), *fields_to_load).first()
    else:
        row = record
    if (not row):
        return
    data = Storage()
    if (OUSR in fields_in_table):
        pi = ('pr_person', 'pr_identity', 'pr_education', 'pr_contact', 'pr_address', 'pr_contact_emergency', 'pr_physical_description', 'pr_group_membership', 'pr_image', 'hrm_training')
        if (OUSR in fields):
            data[OUSR] = fields[OUSR]
        elif ((not row[OUSR]) or (tablename in pi)):
            user_id = None
            if (tablename == 'pr_person'):
                user_id = self.s3_get_user_id(person_id=row[table._id])
            elif ((PID in row) and (tablename in pi)):
                user_id = self.s3_get_user_id(person_id=row[PID])
            elif ((EID in row) and (tablename in pi)):
                user_id = self.s3_get_user_id(pe_id=row[EID])
            if ((not user_id) and self.s3_logged_in() and self.user):
                user_id = self.user.id
            if user_id:
                data[OUSR] = user_id
    if (OGRP in fields_in_table):
        handler = s3db.get_config(tablename, 'owner_group')
        if handler:
            if callable(handler):
                data[OGRP] = handler(table, row)
            else:
                data[OGRP] = handler
        elif (OGRP in fields):
            data[OGRP] = fields[OGRP]
    if (REALM in fields_in_table):
        if ((REALM in row) and row[REALM] and (not force_update)):
            pass
        else:
            if (REALM in fields):
                entity = fields[REALM]
            else:
                entity = 0
            realm_entity = self.get_realm_entity(table, row, entity=entity)
            data[REALM] = realm_entity
    self.s3_update_record_owner(table, row, update=force_update, **data)
