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( '&', '&').replace('<', '<').replace('>', '>') 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)})