def _save_soap_return(self,
                       cr,
                       uid,
                       ids,
                       file_id,
                       filename,
                       xml_node,
                       action,
                       context=None):
     file_obj = self.pool.get('stock.connect.file')
     event_obj = self.pool.get('stock.event')
     resp = file_obj.create(
         cr, uid, {
             'content': xml_to_string(xml_node),
             'name': filename,
             'input': True,
             'stock_connect_id': ids,
             'res_id': file_id,
             'model': 'stock.connect.file'
         }, context)
     event_obj.create(
         cr, uid, {
             'event_code': 'yellowcubesoap_{0}'.format(action),
             'res_id': resp,
             'model': 'stock.connect.file',
         }, context)
     return
 def _save_file(self,
                cr,
                uid,
                ids,
                name,
                _input,
                _type,
                data,
                context=None):
     if context is None:
         context = {}
     if not isinstance(ids, list):
         ids = [ids]
     file_obj = self.pool.get('stock.connect.file')
     if not isinstance(data, str):
         data = xml_to_string(data)
     if _type in [
             'BUR', 'WAR', 'WBA'
     ] and '<!-- Currently no {0}s available -->'.format(_type) in data:
         logger.debug('Ignoring empty {0} file'.format(_type))
         return
     for _id in ids:
         file_obj.create(cr,
                         uid, {
                             'name': name,
                             'input': _input,
                             'type': _type.lower(),
                             'binary_content': False,
                             'content': data,
                             'stock_connect_id': _id
                         },
                         context=context)
    def _send_item(self,
                   cr,
                   uid,
                   ids,
                   server,
                   xml_node,
                   action,
                   schema_name=None,
                   context=None):
        """
        @param server: connection proxy to outside server
        @param xml_node: lxml xml element to send
        @param action: SOAP action to query
        @param schema_name: schema to validate the node against before sending, if set.
        @return: xml_return_message, error_message
        """
        try:
            if schema_name:
                r = validate_xml(schema_name,
                                 xml_node,
                                 print_error=bool(server.config.debug))
                if r:
                    return None, r
            xml_kargs = {'pretty_print': True, 'xml_declaration': False}
            this = self.__this(cr, uid, ids, context)
            root = create_root('{{{soapenv}}}Envelope')
            ns = schema_namespaces['soapenv']
            # 0 soapenv:Header
            xml_header = create_element('Header', ns=ns)
            body = create_element('Body', ns=ns)
            body.append(xml_node)
            root.append(xml_header)
            root.append(body)
            out_data = xml_to_string(root, **xml_kargs)
            parser = etree.XMLParser(remove_blank_text=True)
            out_data = xml_to_string(open_xml(out_data,
                                              repair=False,
                                              parser=parser),
                                     pretty_print=True)

            if this.yc_soapsec_key_path:
                out_data = self._sign_xml(out_data,
                                          keyfile=this.yc_soapsec_key_path,
                                          certfile=this.yc_soapsec_cert_path)

            with _soap_debug(this, action) as soap_debug:
                soap_debug.write('SENDING', out_data)
                r, namespace = server.transport.call(
                    server.proxy,
                    out_data,
                    server.namespace,
                    action,
                    encoding=server.encoding,
                    http_proxy=server.http_proxy,
                    config=server.config,
                    timeout=server.timeout)
                soap_debug.write('RECEIVING', r)
            response = etree.fromstring(r)
            body = response.xpath('//soapenv:Body',
                                  namespaces=schema_namespaces)[0]
            fault = body.xpath('soapenv:Fault', namespaces=schema_namespaces)
            if fault:
                return fault[0], xml_to_string(fault[0]).replace(
                    '&', '&amp;').replace('<', '&lt;').replace('>', '&gt;')
            return body[0], None
        except Exception as e:
            return None, format_exception(e)
        return None, 'Unknown error'
    def _process_gen_response(self, cr, uid, ids, context=None):
        if context is None:
            context = {}
        if not isinstance(ids, list):
            ids = [ids]

        stock_connect_file_obj = self.pool.get('stock.connect.file')

        stock_connect = self.browse(cr, uid, ids[0], context=context)

        domain = [('stock_connect_id', '=', stock_connect.id),
                  ('model', '=', 'stock.connect.file'),
                  ('state', '=', 'draft'), ('type', '=', False),
                  ('input', '=', True), ('error', '=', False)]
        gen_file_ids = stock_connect_file_obj.search(cr,
                                                     uid,
                                                     domain,
                                                     context=context)
        for gen_file in stock_connect_file_obj.browse(cr,
                                                      uid,
                                                      gen_file_ids,
                                                      context=context):
            # Find the elements and mark them
            if 'GEN_Response>' in gen_file.content:
                gen_file.write({'type': 'gen', 'state': 'ready'})
        domain[2] = ('state', '=', 'ready')
        domain[3] = ('type', '=', 'gen')

        def __read_file(xml_node):
            return {
                'type': nspath(xml, 'gen:MessageType')[0].text,
                'ref': nspath(xml, 'gen:Reference')[0].text,
                'status_text': nspath(xml, 'gen:StatusText')[0].text,
                'status_code': int(nspath(xml, 'gen:StatusCode')[0].text),
                'status_type': nspath(xml, 'gen:StatusType')[0].text,
            }

        server = self._get_proxy(cr, uid, ids, context=context)
        gen_file_ids = stock_connect_file_obj.search(cr,
                                                     uid,
                                                     domain,
                                                     order='id ASC',
                                                     context=context)
        for gen_file in stock_connect_file_obj.browse(cr,
                                                      uid,
                                                      gen_file_ids,
                                                      context=context):
            # Process all the files
            try:
                original_file = stock_connect_file_obj.browse(
                    cr, uid, gen_file.res_id, context)
                if original_file.server_ack:
                    # Only process if required
                    msg = _("Ignoring Response on behalf old ACK on file")
                    logger.warning(msg)
                    gen_file.write({
                        'error': False,
                        'state': 'cancel',
                        'info': msg
                    })
                    continue
                xml = open_xml(gen_file.content, repair=False)
                values = __read_file(xml)
                if values['status_type'] != 'S' or values['status_code'] > 100:
                    # Don't re-process errors
                    raise Exception(_("Error on Status response"),
                                    values['status_text'])
                elif values['status_code'] == 100:
                    # If it was finished, don't reprocess
                    gen_file.write({
                        'state': 'done',
                        'info': values['status_text'],
                        'internal_index': values['status_code']
                    })
                    original_file.write({'server_ack': True})
                else:
                    # Send a request
                    ns = schema_namespaces['gen_req']
                    xml_req = create_root('{{{gen_req}}}GEN_STATUS')
                    xml_req.append(
                        self._get_control_reference(cr,
                                                    uid,
                                                    ids,
                                                    ns,
                                                    values['type'],
                                                    context=context))
                    xml_req.append(
                        create_element('Reference', text=values['ref'], ns=ns))
                    xml_ret, err_ret = self._send_item(
                        cr,
                        uid,
                        ids,
                        server,
                        xml_req,
                        action='GetInsertArticleMasterDataStatus',
                        schema_name='gen_req',
                        context=context)
                    if err_ret:
                        # Write errors on file
                        gen_file.write({'error': True, 'info': err_ret})
                    else:
                        values_ret = __read_file(xml_ret)
                        if values_ret['status_type'] != 'S' or values_ret[
                                'status_code'] > 100:
                            # Strange status codes are errors
                            gen_file.write({
                                'error':
                                True,
                                'info':
                                xml_to_string(xml_ret),
                                'internal_index':
                                values_ret['status_code']
                            })
                        elif values_ret['status_code'] < 100:
                            # Modify the file if pending, avoiding excess of inputs
                            gen_file.write({
                                'content':
                                xml_to_string(xml_ret),
                                'internal_index':
                                values_ret['status_code']
                            })
                        else:
                            # Propagate end
                            gen_file.write({
                                'state':
                                'done',
                                'content':
                                xml_to_string(xml_ret),
                                'info':
                                values_ret['status_text'],
                                'internal_index':
                                values_ret['status_code']
                            })
                            original_file.write({'server_ack': True})
            except Exception as e:
                logger.error(format_exception(e))
                gen_file.write({'error': True, 'info': format_exception(e)})