乐于分享
好东西不私藏

odoo集成onlyoffice时如何保持一致性

odoo集成onlyoffice时如何保持一致性
业务场景:当用户小张通过onlyoffice打开附件编辑时,此时用户小李通过后台python语言修改此附件
风险:一致性错误,版本混乱,小李通过odoo修改此附件后,随后小张又将此附件覆盖
原因:小张在odoo编辑的附件与小李在onlyoffice的附件不一致。如果在onlyoffice设置的模式为“快速”,onlyoffice会对附件修改自动保存,但是此保存仅在onlyoffice缓存中,没有同步到odoo系统,有其他机制触发同步;如果在onlyoffice设置为“严格”,需人工点击保存按钮,随后将附件同步到odoo系统。
解决方案:小张在修改附件前将onlyoffice的附件强制保存,同步到odoo,随后将onlyoffice此时编辑该附件的用户小李强制离线,如果想再次编辑,小李需从odoo中打开。
代码:
1、调用onlyoffice接口的统一方法,具体详情可以登录官网查看API
import requestsimport jsonimport loggingfrom odoo.addons.onlyoffice_odoo.utils import jwt_utils, config_utils_logger = logging.getLogger(__name__)def call_command_service_with_header_jwt(env, command_payload):    """    调用命令服务,并将 JWT Token 放在 Authorization Header 中。    command_payload 是命令本身需要的参数 (不含 token)。    """    token = jwt_utils.encode_payload(env, command_payload)    DOC_SERVER_URL = config_utils.get_doc_server_public_url(env)    COMMAND_SERVICE_URL = f"{DOC_SERVER_URL}/command"    full_payload = {        "token": token,        **command_payload # 合并命令本身的参数    }    jwt_header = config_utils.get_jwt_header(env)    headers = {        "Content-Type""application/json",        jwt_header: f"Bearer {token}" # 使用配置的 Header 名称和 "Bearer " 前缀    }    _logger.info(f"--- command_payload: {command_payload} ---")    _logger.info(f"Request Headers: {headers}")    _logger.info(f"Request Payload: {json.dumps(full_payload, indent=2)}")    try:        response = requests.post(            COMMAND_SERVICE_URL,            headers=headers,            json=full_payload # 将包含 token 和命令参数的 payload 发送        )        response.raise_for_status()        _logger.info(f"Response Status Code: {response.status_code}")        _logger.info(f"Response Body: {json.dumps(response.json(), indent=2)}")        return response.json()    except requests.exceptions.RequestException as e:        _logger.info(f"Error calling command service for {command_payload}{e}")        if hasattr(e, 'response'and e.response is not None:            _logger.info(f"Response Status Code: {e.response.status_code}")            _logger.info(f"Response Body: {e.response.text}")        return None
2、在odoo的model中实现业务逻辑,强制保存、获取正在编辑用户、强制离线
def _out_user_with_of(self):    """ 强制用户离线 """    for record in self:        try:            attachment = record.attachment_ids[0]            data = attachment.read(["id""checksum""public""name""access_token"])[0]            key = str(data["id"]) + str(data["checksum"])            # 强制保存            call_command_service_with_header_jwt(self.env, {"key": key, "c""forcesave"})            # 获取用户            payload_info_cmd = {"key": key, "c""info"}            ol_info = call_command_service_with_header_jwt(self.env, payload_info_cmd)            # 强制离线            if ol_info.get("error") == 0:                call_command_service_with_header_jwt(self.env, {"key": key, "c""drop""users": ol_info.get('users')})            time.sleep(2)        except Exception as e:            _logger.error(f"强制onlyoffice用户离线异常:{e.args}")            pass