def _get_wab_for_soap(self, cr, uid, ids, file_id, context=None):
        ns = schema_namespaces['wab']
        _file = self.pool.get('stock.connect.file').browse(
            cr, uid, file_id, context)
        wab_root = open_xml(_file.content, 'wab')
        order_docs = wab_root.xpath('//wab:OrderDocuments',
                                    namespaces=schema_namespaces)[0]
        names = [x.text for x in order_docs[0]]
        order_docs.remove(order_docs[0])
        for att in _file.attachments:
            if att.name not in names:
                raise Exception(
                    'Unknown file {0}'.format(att.name),
                    'Expecting one of: {0}'.format(', '.join.names))
            names.remove(att.name)
            doc = create_element('Docs', ns=ns)
            doc.append(
                create_element('DocType',
                               text=att.name.split('_')[1][:2],
                               ns=ns))
            doc.append(create_element('DocMimeType', text=att.name[-3:],
                                      ns=ns))
            doc.append(create_element('DocStream', text=att.datas, ns=ns))
            order_docs.append(doc)

        return wab_root
 def _get_art_for_soap(self, cr, uid, ids, file_id, context=None):
     _file = self.pool.get('stock.connect.file').browse(
         cr, uid, file_id, context)
     art_root = open_xml(_file.content, 'art')
     ns = schema_namespaces['art']
     ret = []
     control_reference = nspath(art_root, '//art:ControlReference')[0]
     pos_no = 0
     pending = False
     limit = context['limit_files']
     if _file.internal_index < 0:
         return ret
     for article in nspath(art_root, '//art:Article'):
         # Have we read enough?
         if limit[0] and limit[0] <= limit[1]:
             pending = True
             break
         # The pointer points to the next one
         pos_no += 1
         # Are we reading new items?
         if pos_no > _file.internal_index:
             limit[1] += 1
         else:
             continue
         new_root = create_root('{{{art}}}ART')
         new_root.append(copy.deepcopy(control_reference))
         art_list = create_element('ArticleList', ns=ns)
         art_list.append(article)
         new_root.append(art_list)
         ret.append(new_root)
     if pending:
         _file.write({'internal_index': pos_no})
     else:
         _file.write({'internal_index': -1})
     return ret
    def _get_bur_soap_file(self,
                           cr,
                           uid,
                           ids,
                           server,
                           action,
                           ns_name,
                           root_name,
                           _type,
                           context=None):
        ns = schema_namespaces[ns_name]
        root = create_element(root_name, ns=ns)
        root.append(
            self._get_control_reference(cr, uid, ids, ns, _type, context))
        this = self.__this(cr, uid, ids, context)
        _now = datetime.now()

        if this.yc_last_bur_check:
            _old = datetime.strptime(this.yc_last_bur_check,
                                     DEFAULT_SERVER_DATETIME_FORMAT)
            diff = _now - _old
            diff = int(diff.days)
            if diff > 999:
                diff = 999
            if diff == 0 and _now.day != _old.day:
                # The never-feed-after-midnight check
                diff = 1
            root.append(create_element('ElapsedDays', text=diff, ns=ns))
        else:
            # By default we send 1 day
            root.append(create_element('ElapsedDays', text=1, ns=ns))

        if self._get_soap_file(cr, uid, ids, server, action, ns_name,
                               root_name, _type, context, root):
            # If everything goes clear, we set the last check
            this.write({
                'yc_last_bur_check':
                _now.strftime(DEFAULT_SERVER_DATETIME_FORMAT)
            })
 def _get_soap_file(self,
                    cr,
                    uid,
                    ids,
                    server,
                    action,
                    ns_name,
                    root_name,
                    _type,
                    context=None,
                    root=None):
     if context is None:
         context = {}
     if root is None:
         # If the root is missing, we may create it
         if _type == 'BUR':
             # BUR is very special, so delegate
             return self._get_bur_soap_file(cr, uid, ids, server, action,
                                            ns_name, root_name, _type,
                                            context)
         ns = schema_namespaces[ns_name]
         root = create_element(root_name, ns=ns)
         root.append(
             self._get_control_reference(cr, uid, ids, ns, _type, context))
     ret, err = self._send_item(cr,
                                uid,
                                ids,
                                server,
                                root,
                                action,
                                context=context)
     if err:
         self._save_error(cr,
                          uid,
                          ids,
                          _ERR_MSG.format(ns_name, '', err),
                          context=context,
                          show_errors=bool(ret or False))
         return False
     self._save_file(cr, uid, ids, '{0}_{1}'.format(self._get_timestamp(),
                                                    _type), True, _type,
                     ret, context)
     return ret or True
    def _get_control_reference(self, cr, uid, ids, ns, type_, context=None):
        if context is None:
            context = {}
        if isinstance(ids, list):
            ids = ids[0]
        connect = self.pool.get('stock.connect').browse(cr, uid, ids, context)

        ts = self._get_timestamp()

        ret = create_element('ControlReference', ns=ns)
        ret.append(create_element('Type', ns=ns, text=type_))
        ret.append(create_element('Sender', ns=ns, text=connect.yc_sender))
        ret.append(create_element('Receiver', ns=ns, text=connect.yc_receiver))
        ret.append(create_element('Timestamp', ns=ns, text=ts))
        ret.append(
            create_element('OperatingMode',
                           ns=ns,
                           text=connect.yc_operating_mode))
        ret.append(create_element('Version', ns=ns, text='1.0'))
        return ret
    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)})