def __register__(cls, module_name): Party = Pool().get('party.party') Sale = Pool().get('sale.sale') Model = Pool().get('ir.model') ModelField = Pool().get('ir.model.field') Property = Pool().get('ir.property') TableHandler = backend.get('TableHandler') cursor = Transaction().cursor table = TableHandler(cursor, cls, module_name) migration_needed = False if not table.column_exist('credit_account'): migration_needed = True super(Payment, cls).__register__(module_name) if migration_needed and not Pool.test: # Migration # Set party's receivable account as the credit_account on # sale payments payment = cls.__table__() party = Party.__table__() property = Property.__table__() sale = Sale.__table__() account_model, = Model.search([ ('model', '=', 'party.party'), ]) account_receivable_field, = ModelField.search([ ('model', '=', account_model.id), ('name', '=', 'account_receivable'), ('ttype', '=', 'many2one'), ]) update = payment.update( columns=[payment.credit_account], values=[ Trim( Substring(property.value, ',.*'), 'LEADING', ',' ).cast(cls.credit_account.sql_type().base) ], from_=[sale, party, property], where=( payment.sale == sale.id ) & ( sale.party == party.id ) & ( property.res == Concat(Party.__name__ + ',', party.id) ) & ( property.field == account_receivable_field.id ) & ( property.company == sale.company ) ) cursor.execute(*update)
def _get_balance_query(self, end_date, start_date=None, unreconciled_lines_only=True): """ Returns a python-sql object that can be used to query the move tables. Does not select anything in the query and leaves it to the programmer calling this api. """ MoveLine = Pool().get('account.move.line') Account = Pool().get('account.account') Move = Pool().get('account.move') User = Pool().get('res.user') line = MoveLine.__table__() account = Account.__table__() move = Move.__table__() user_id = Transaction().user if user_id == 0 and 'user' in Transaction().context: user_id = Transaction().context['user'] user = User(user_id) if not user.company: return _ZERO company_id = user.company.id line_query, _ = MoveLine.query_get(line) date_where = (move.date <= end_date) if start_date is not None: date_where &= (move.date >= start_date) tables = { 'account.move.line': line, 'account.account': account, 'account.move': move, } query = line.join( account, condition=account.id == line.account ).join( move, condition=line.move == move.id ).select( where=account.active & (account.kind.in_(('receivable', 'payable'))) & (line.party == self.id) & (account.company == company_id) & line_query & date_where ) if unreconciled_lines_only: query.where &= (line.reconciliation == None) # noqa return query, tables
def _get_products(self): """ Return a query based on the node settings. This is separated for easy subclassing. The returned value would be a tuple with the dollowing elements: * The Model instance * Select query instance * The Table instance for the SQL Pagination """ Node = Pool().get('product.tree_node') Product = Pool().get('product.product') ProductTemplate = Pool().get('product.template') ProductNodeRelation = Pool().get('product.product-product.tree_node') ProductTable = Product.__table__() TemplateTable = ProductTemplate.__table__() RelTable = ProductNodeRelation.__table__() NodeTable = Node.__table__() if self.display == 'product.product': query = ProductTable.join( TemplateTable, condition=(TemplateTable.id == ProductTable.template)).join( RelTable, condition=(RelTable.product == ProductTable.id)).join( NodeTable, condition=(RelTable.node == NodeTable.id)).select( where=(TemplateTable.active & ProductTable.displayed_on_eshop & (NodeTable.left >= Literal(self.left)) & (NodeTable.right <= Literal(self.right))), order_by=RelTable.sequence.asc) return Product, query, ProductTable elif self.display == 'product.template': query = TemplateTable.join( ProductTable, condition=(TemplateTable.id == ProductTable.template)).join( RelTable, condition=(RelTable.product == ProductTable.id)).join( NodeTable, condition=(RelTable.node == NodeTable.id)).select( where=(TemplateTable.active & ProductTable.displayed_on_eshop & (NodeTable.left >= Literal(self.left)) & (NodeTable.right <= Literal(self.right))), order_by=RelTable.sequence.asc) return ProductTemplate, query, TemplateTable
def get_recent_sales(cls): """ Return sales of current channel, which were made within last 5 days and are in draft state. Sort by write_date or create_date of Sale and sale lines. """ SaleLine = Pool().get('sale.line') context = Transaction().context date = (datetime.now() - timedelta(days=5)).strftime('%Y-%m-%d %H:%M:%S') current_channel = context['current_channel'] SaleTable = cls.__table__() SaleLineTable = SaleLine.__table__() cursor = Transaction().cursor query = SaleTable.join( SaleLineTable, condition=(SaleTable.id == SaleLineTable.sale)).select( SaleTable.id, where=((SaleTable.channel == Literal(current_channel)) & (SaleTable.state.in_( ['draft', 'quotation', 'confirmed', 'processing'])) & ((SaleTable.write_date >= Literal(date)) | (SaleTable.create_date >= Literal(date)))), order_by=(SaleLineTable.write_date.desc, SaleLineTable.create_date.desc, SaleTable.write_date.desc, SaleTable.create_date.desc)) cursor.execute(*query) ids = [x[0] for x in cursor.fetchall()] return [cls(id).serialize('recent_sales') for id in ids]
def table_query(cls): Opportunity = Pool().get('sale.opportunity') opportunity = Opportunity.__table__() return opportunity.select( Max(opportunity.create_uid).as_('create_uid'), Max(opportunity.create_date).as_('create_date'), Max(opportunity.write_uid).as_('write_uid'), Max(opportunity.write_date).as_('write_date'), opportunity.company, Count(Literal(1)).as_('number'), Sum( Case((opportunity.state.in_( cls._converted_state()), Literal(1)), else_=Literal(0))).as_('converted'), Sum( Case((opportunity.state.in_(cls._won_state()), Literal(1)), else_=Literal(0))).as_('won'), Sum( Case((opportunity.state.in_(cls._lost_state()), Literal(1)), else_=Literal(0))).as_('lost'), Sum(opportunity.amount).as_('amount'), Sum( Case((opportunity.state.in_( cls._converted_state()), opportunity.amount), else_=Literal(0))).as_('converted_amount'), Sum( Case((opportunity.state.in_( cls._won_state()), opportunity.amount), else_=Literal(0))).as_('won_amount'))
def __register__(cls, module_name): Identifier = Pool().get('party.identifier') cursor = Transaction().connection.cursor() TableHandler = backend.get('TableHandler') sql_table = cls.__table__() identifier = Identifier.__table__() super(Party, cls).__register__(module_name) table = TableHandler(cls, module_name) # Migration from 4.0: Move sepa_creditor_identifier to identifier if table.column_exist('sepa_creditor_identifier'): select = sql_table.select( Literal(0), CurrentTimestamp(), sql_table.id, Literal('sepa'), sql_table.sepa_creditor_identifier, where=((sql_table.sepa_creditor_identifier != Null) & (sql_table.sepa_creditor_identifier != ""))) cursor.execute(*identifier.insert(columns=[ identifier.create_uid, identifier.create_date, identifier.party, identifier.type, identifier.code ], values=select)) table.drop_column('sepa_creditor_identifier')
def search(cls, args, offset=0, limit=None, order=None, count=False, query=False): lines = super().search(args, offset, limit, order, count, query) Move = Pool().get('account.move') cursor = Transaction().connection.cursor() table = cls.__table__() move = Move.__table__() if lines and isinstance(lines, list): red_sql = reduce_ids(table.id, [x.id for x in lines]) # This sorting criteria must be the one used by the 'balance' # functional field above, so remember to modify that if you # want to change the order. cursor.execute(*table.join(move, condition=table.move == move.id).select(table.id, where=red_sql, order_by=(move.date, move.number, table.id))) result = cursor.fetchall() ids = [x[0] for x in result] lines = cls.browse(ids) return lines
def __register__(cls, module_name): TableHandler = backend.get('TableHandler') cursor = Transaction().cursor table = TableHandler(cursor, cls, module_name) sql_table = cls.__table__() # Migration from 2.2 new field currency created_currency = table.column_exist('currency') super(ProductSupplier, cls).__register__(module_name) # Migration from 2.2 fill currency if not created_currency: Company = Pool().get('company.company') company = Company.__table__() limit = cursor.IN_MAX cursor.execute(*sql_table.select(Count(sql_table.id))) product_supplier_count, = cursor.fetchone() for offset in range(0, product_supplier_count, limit): cursor.execute(*sql_table.join(company, condition=sql_table.company == company.id ).select(sql_table.id, company.currency, order_by=sql_table.id, limit=limit, offset=offset)) for product_supplier_id, currency_id in cursor.fetchall(): cursor.execute(*sql_table.update( columns=[sql_table.currency], values=[currency_id], where=sql_table.id == product_supplier_id)) # Migration from 2.4: drop required on sequence table.not_null_action('sequence', action='remove') # Migration from 2.6: drop required on delivery_time table.not_null_action('delivery_time', action='remove')
def get_creationdate(cls, uri, cache=None): Party = Pool().get('party.party') party = Party.__table__() party_id = cls.vcard(uri) cursor = Transaction().connection.cursor() if party_id is None: raise DAV_NotFound if party_id: if cache is not None: cache.setdefault('_contact', {}) ids = cache['_contact'].keys() if party_id not in ids: ids.append(party_id) elif 'creationdate' in cache['_contact'][party_id]: return cache['_contact'][party_id]['creationdate'] else: ids = [party_id] res = None for sub_ids in grouped_slice(ids): red_sql = reduce_ids(party.id, sub_ids) cursor.execute(*party.select(party.id, Extract('EPOCH', party.create_date), where=red_sql)) for party_id2, date in cursor.fetchall(): if party_id2 == party_id: res = date if cache is not None: cache['_contact'].setdefault(party_id2, {}) cache['_contact'][party_id2]['creationdate'] = date if res is not None: return res return super(Collection, cls).get_creationdate(uri, cache=cache)
def merge_into(self, target): """Merge current record to target party. """ ModelField = Pool().get('ir.model.field') # Inactive party first self.active = False self.save() cursor = Transaction().connection.cursor() if self._history: # Update the party history first. # # The approach is to make the history of all merged records # also the history of the target record. party_history_table = self.__table_history__() cursor.execute( *party_history_table.update( columns=[party_history_table.id], values=[target.id], where=(party_history_table.id == self.id) ) ) party_fields = ModelField.search([ ('relation', '=', 'party.party'), ('ttype', '=', 'many2one'), ]) for field in party_fields: Model = Pool().get(field.model.model) if isinstance(getattr(Model, field.name), fields.Function): continue if not hasattr(Model, '__table__'): continue if Model.table_query(): continue sql_table = Model.__table__() # Update direct foreign key references cursor.execute(*sql_table.update( columns=[getattr(sql_table, field.name)], values=[target.id], where=(getattr(sql_table, field.name) == self.id) )) if Model._history: # If historization is enabled on the model # then the party value in the history should # now point to the target party id since the # history of the current party is already the history of # target party. history_table = Model.__table_history__() cursor.execute(*history_table.update( columns=[getattr(history_table, field.name)], values=[target.id], where=(getattr(history_table, field.name) == self.id) ))
def table_query(self=None): price_profit_loss = Pool().get('hrp_report.price_profit_loss_content') ProfitLoss = price_profit_loss.__table__() where = Literal(True) condition = [] if Transaction().context.get('location') != None: condition.append(('location', '=', Transaction().context.get('location'))) if Transaction().context.get('start_time') != None: condition.append(('effective_date', '>=', Transaction().context.get('start_time'))) if Transaction().context.get('end_time') != None: condition.append(('effective_date', '<=', Transaction().context.get('end_time'))) if Transaction().context.get('drug_type') != None: if Transaction().context.get('drug_type') == '06': pass else: condition.append(('drug_type', '=', Transaction().context.get('drug_type'))) product_ids = price_profit_loss.search([condition], query=True, order=[]) where &= ProfitLoss.id.in_(product_ids) Result = ProfitLoss.select( ProfitLoss.id.as_('id'), Max(ProfitLoss.create_uid).as_('create_uid'), Max(ProfitLoss.create_date).as_('create_date'), Max(ProfitLoss.write_uid).as_('write_uid'), Max(ProfitLoss.write_date).as_('write_date'), ProfitLoss.uom, where=where, group_by=ProfitLoss.id) return Result
def merge_into(self, target): """Merge current record to target party. """ ModelField = Pool().get('ir.model.field') party_fields = ModelField.search([ ('relation', '=', 'party.party'), ('ttype', '=', 'many2one'), ]) # Inactive party first self.active = False self.save() cursor = Transaction().cursor for field in party_fields: Model = Pool().get(field.model.model) if isinstance(getattr(Model, field.name), fields.Function): continue if not hasattr(Model, '__table__'): continue sql_table = Model.__table__() cursor.execute(*sql_table.update( columns=[getattr(sql_table, field.name)], values=[target.id], where=(getattr(sql_table, field.name) == self.id)))
def get_creationdate(cls, uri, cache=None): Party = Pool().get('party.party') party = Party.__table__() party_id = cls.vcard(uri) cursor = Transaction().cursor if party_id is None: raise DAV_NotFound if party_id: if cache is not None: cache.setdefault('_contact', {}) ids = cache['_contact'].keys() if party_id not in ids: ids.append(party_id) elif 'creationdate' in cache['_contact'][party_id]: return cache['_contact'][party_id]['creationdate'] else: ids = [party_id] res = None for sub_ids in grouped_slice(ids): red_sql = reduce_ids(party.id, sub_ids) cursor.execute(*party.select(party.id, Extract('EPOCH', party.create_date), where=red_sql)) for party_id2, date in cursor.fetchall(): if party_id2 == party_id: res = date if cache is not None: cache['_contact'].setdefault(party_id2, {}) cache['_contact'][party_id2]['creationdate'] = date if res is not None: return res return super(Collection, cls).get_creationdate(uri, cache=cache)
def merge_into(self, target): """Merge current record to target party. """ ModelField = Pool().get('ir.model.field') # Inactive party first self.active = False self.save() cursor = Transaction().connection.cursor() if self._history: # Update the party history first. # # The approach is to make the history of all merged records # also the history of the target record. party_history_table = self.__table_history__() cursor.execute(*party_history_table.update( columns=[party_history_table.id], values=[target.id], where=(party_history_table.id == self.id))) party_fields = ModelField.search([ ('relation', '=', 'party.party'), ('ttype', '=', 'many2one'), ]) for field in party_fields: Model = Pool().get(field.model.model) if isinstance(getattr(Model, field.name), fields.Function): continue if not hasattr(Model, '__table__'): continue if Model.table_query(): continue sql_table = Model.__table__() # Update direct foreign key references cursor.execute(*sql_table.update( columns=[getattr(sql_table, field.name)], values=[target.id], where=(getattr(sql_table, field.name) == self.id))) if Model._history: # If historization is enabled on the model # then the party value in the history should # now point to the target party id since the # history of the current party is already the history of # target party. history_table = Model.__table_history__() cursor.execute(*history_table.update( columns=[getattr(history_table, field.name)], values=[target.id], where=(getattr(history_table, field.name) == self.id)))
def get_move_lines_maturing(cls, party, start_date, end_date): """ Returns the move lines maturing in the given date range """ AccountMoveLines = Pool().get('account.move.line') AccountMove = Pool().get('account.move') User = Pool().get('res.user') Account = Pool().get('account.account') user = User(Transaction().user) cursor = Transaction().connection.cursor() line = AccountMoveLines.__table__() move = AccountMove.__table__() account = Account.__table__() line_query, _ = AccountMoveLines.query_get(line) sub_query = line.join( account, condition=account.id == line.account ) query = sub_query.join( move, condition=line.move == move.id, ).select( line.id, where=account.active & (line.party == party.id) & (account.company == user.company.id) & (account.kind.in_(('receivable', 'payable'))) & (line.maturity_date >= start_date) & (line.maturity_date <= end_date) & line_query, order_by=move.date.asc ) cursor.execute(*query) move_line_ids = [id[0] for id in cursor.fetchall()] move_lines = AccountMoveLines.browse(move_line_ids) return move_lines
def order_field(tables): Sample = Pool().get('lims.sample') field = Sample._fields[name] table, _ = tables[None] sample_tables = tables.get('sample') if sample_tables is None: sample = Sample.__table__() sample_tables = { None: (sample, sample.id == table.sample), } tables['sample'] = sample_tables return field.convert_order(name, sample_tables, Sample)
def order_field(tables): Equipment = Pool().get('lims.equipment') field = Equipment._fields[name] table, _ = tables[None] equipment_tables = tables.get('equipment') if equipment_tables is None: equipment = Equipment.__table__() equipment_tables = { None: (equipment, equipment.id == table.equipment), } tables['equipment'] = equipment_tables return field.convert_order(name, equipment_tables, Equipment)
def getter_latest_book(cls, authors, name): result = {x.id: None for x in authors} Book = Pool().get('library.book') book = Book.__table__() sub_book = Book.__table__() cursor = Transaction().connection.cursor() sub_query = sub_book.select( sub_book.author, Max(Coalesce(sub_book.publishing_date, datetime.date.min), window=Window([sub_book.author])).as_('max_date'), where=sub_book.author.in_([x.id for x in authors])) cursor.execute( *book.join(sub_query, condition=(book.author == sub_query.author) & (Coalesce(book.publishing_date, datetime.date.min) == sub_query.max_date)).select(book.author, book.id)) for author_id, book in cursor.fetchall(): result[author_id] = book return result
def __register__(cls, module_name): TableHandler = backend.get('TableHandler') transaction = Transaction() cursor = transaction.connection.cursor() table = TableHandler(cls, module_name) sql_table = cls.__table__() # Migration from 2.2 new field currency created_currency = table.column_exist('currency') super(ProductSupplier, cls).__register__(module_name) # Migration from 2.2 fill currency if not created_currency: Company = Pool().get('company.company') company = Company.__table__() limit = transaction.database.IN_MAX cursor.execute(*sql_table.select(Count(sql_table.id))) product_supplier_count, = cursor.fetchone() for offset in range(0, product_supplier_count, limit): cursor.execute(*sql_table.join( company, condition=sql_table.company == company.id).select( sql_table.id, company.currency, order_by=sql_table.id, limit=limit, offset=offset)) for product_supplier_id, currency_id in cursor.fetchall(): cursor.execute(*sql_table.update( columns=[sql_table.currency], values=[currency_id], where=sql_table.id == product_supplier_id)) # Migration from 2.4: drop required on sequence table.not_null_action('sequence', action='remove') # Migration from 2.6: drop required on delivery_time table.not_null_action('delivery_time', action='remove') # Migration from 3.8: change delivery_time inte timedelta lead_time if table.column_exist('delivery_time'): cursor.execute( *sql_table.select(sql_table.id, sql_table.delivery_time)) for id_, delivery_time in cursor.fetchall(): if delivery_time is None: continue lead_time = datetime.timedelta(days=delivery_time) cursor.execute( *sql_table.update([sql_table.lead_time], [lead_time], where=sql_table.id == id_)) table.drop_column('delivery_time')
def getter_number_of_books(cls, editors, name): result = {x.id: 0 for x in editors} Book = Pool().get('library.book') book = Book.__table__() cursor = Transaction().connection.cursor() cursor.execute( *book.select(book.editor, Count(book.id), where=book.editor.in_([x.id for x in editors]), group_by=[book.editor])) for editor_id, count in cursor.fetchall(): result[editor_id] = count return result
def getter_number_of_exemplaries(cls, books, name): result = {x.id: 0 for x in books} Exemplary = Pool().get('library.book.exemplary') exemplary = Exemplary.__table__() cursor = Transaction().connection.cursor() cursor.execute( *exemplary.select(exemplary.book, Count(exemplary.id), where=exemplary.book.in_([x.id for x in books]), group_by=[exemplary.book])) for book_id, count in cursor.fetchall(): result[book_id] = count return result
def write(cls, *args): config = cls(1) if config.party_phonecountry: party_phonecountry_code = config.party_phonecountry.code else: party_phonecountry_code = '' super(Configuration, cls).write(*args) if config.party_phonecountry: party_phonecountry_code_new = config.party_phonecountry.code else: party_phonecountry_code_new = '' if phonenumbers and party_phonecountry_code_new != party_phonecountry_code: ContactMechanism = Pool().get('party.contact_mechanism') table = ContactMechanism.__table__() cursor = Transaction().connection.cursor() for contact in ContactMechanism.search([('type', 'in', _PHONE_TYPES)]): values = {} # value_compact use PhoneNumberFormat.E164 phonenumber = phonenumbers.parse(contact.value_compact) region_code = phonenumbers.region_code_for_country_code( phonenumber.country_code) if region_code == party_phonecountry_code: # consider phonenumber with extensions p.e. 918041213 ext.412 phonenumber = phonenumbers.parse(contact.value, region_code) value = phonenumbers.format_number( phonenumber, PhoneNumberFormat.INTERNATIONAL) cursor.execute( *table.update(columns=[table.value], values=[value], where=(table.id == contact.id))) elif region_code == party_phonecountry_code_new: phonenumber = phonenumbers.parse(contact.value) value = phonenumbers.format_number( phonenumber, PhoneNumberFormat.NATIONAL) cursor.execute( *table.update(columns=[table.value], values=[value], where=(table.id == contact.id)))
def get_lastmodified(cls, uri, cache=None): Todo = Pool().get('calendar.todo') todo = Todo.__table__() transaction = Transaction() cursor = transaction.connection.cursor() calendar_id = cls.calendar(uri) if calendar_id and (uri[10:].split('/', 1) + [None])[1]: todo_id = cls.todo(uri, calendar_id=calendar_id) if todo_id: if cache is not None: cache.setdefault('_calendar', {}) cache['_calendar'].setdefault(Todo.__name__, {}) ids = cache['_calendar'][Todo.__name__].keys() if todo_id not in ids: ids.append(todo_id) elif 'lastmodified' in cache['_calendar'][ Todo.__name__][todo_id]: return cache['_calendar'][ Todo.__name__][todo_id]['lastmodified'] else: ids = [todo_id] res = None for sub_ids in grouped_slice(ids, transaction.database.IN_MAX / 2): red_id_sql = reduce_ids(todo.id, sub_ids) red_parent_sql = reduce_ids(todo.parent, sub_ids) cursor.execute(*todo.select( Coalesce(todo.parent, todo.id), Max( Extract( 'EPOCH', Coalesce(todo.write_date, todo.create_date))), where=red_id_sql | red_parent_sql, group_by=(todo.parent, todo.id))) for todo_id2, date in cursor.fetchall(): if todo_id2 == todo_id: res = date if cache is not None: cache['_calendar'][Todo.__name__]\ .setdefault(todo_id2, {}) cache['_calendar'][ Todo.__name__][todo_id2]['lastmodified'] = date if res is not None: return res return super(Collection, cls).get_lastmodified(uri, cache=cache)
def __register__(cls, module_name): TableHandler = backend.get('TableHandler') cursor = Transaction().connection.cursor() ContactMech = Pool().get('party.contact_mechanism') sql_table = cls.__table__() contact_mech_table = ContactMech.__table__() super(Address, cls).__register__(module_name) table = TableHandler(cls, module_name) if table.column_exist('phone_number'): cursor.execute(*sql_table.update(columns=[sql_table.phone], values=[contact_mech_table.value], from_=[contact_mech_table], where=sql_table.phone_number == contact_mech_table.id)) table.column_rename("phone_number", "phone_number_deprecated")
def transition_reasign(self): Invoice = Pool().get('account.invoice') cursor = Transaction().connection.cursor() invoice_ids = Transaction().context['active_ids'] invoices = Invoice.browse(invoice_ids) value = self.start.aeat347_operation_key invoice = Invoice.__table__() # Update to allow to modify key for posted invoices cursor.execute(*invoice.update(columns=[ invoice.aeat347_operation_key, ], values=[value], where=In(invoice.id, invoice_ids))) Invoice.create_aeat347_records(invoices) return 'done'
def order_component(cls, tables): Component = Pool().get('lims.component') kind_field = Component._fields['kind'] location_field = Component._fields['location'] sample, _ = tables[None] component_tables = tables.get('component') if component_tables is None: component = Component.__table__() component_tables = { None: (component, component.id == sample.component), } tables['component'] = component_tables order = ( kind_field.convert_order('kind', component_tables, Component) + location_field.convert_order('location', component_tables, Component)) return order
def __register__(cls, module_name): TableHandler = backend.get('TableHandler') cursor = Transaction().connection.cursor() ContactMech = Pool().get('party.contact_mechanism') sql_table = cls.__table__() contact_mech_table = ContactMech.__table__() super(Address, cls).__register__(module_name) table = TableHandler(cls, module_name) if table.column_exist('phone_number'): cursor.execute(*sql_table.update( columns=[sql_table.phone], values=[contact_mech_table.value], from_=[contact_mech_table], where=sql_table.phone_number == contact_mech_table.id) ) table.column_rename("phone_number", "phone_number_deprecated")
def order_field(tables): Service = Pool().get('lims.service') field = Service._fields[name] table, _ = tables[None] service_tables = tables.get('service') if service_tables is None: service = Service.__table__() service_tables = { None: (service, (table.origin.like('lims.service,%') & (Service.id.sql_cast( Substring(table.origin, Position(',', table.origin) + Literal(1))) == service.id))), } tables['service'] = service_tables return field.convert_order(name, service_tables, Service)
def get_creationdate(cls, uri, cache=None): Todo = Pool().get('calendar.todo') todo = Todo.__table__() cursor = Transaction().connection.cursor() calendar_id = cls.calendar(uri) if not calendar_id: calendar_id = cls.calendar(uri, ics=True) if calendar_id and (uri[10:].split('/', 1) + [None])[1]: todo_id = cls.todo(uri, calendar_id=calendar_id) if todo_id: if cache is not None: cache.setdefault('_calendar', {}) cache['_calendar'].setdefault(Todo.__name__, {}) ids = cache['_calendar'][Todo.__name__].keys() if todo_id not in ids: ids.append(todo_id) elif 'creationdate' in cache['_calendar'][ Todo.__name__][todo_id]: return cache['_calendar'][ Todo.__name__][todo_id]['creationdate'] else: ids = [todo_id] res = None for sub_ids in grouped_slice(ids): red_sql = reduce_ids(todo.id, sub_ids) cursor.execute( *todo.select(todo.id, Extract('EPOCH', todo.create_date), where=red_sql)) for todo_id2, date in cursor.fetchall(): if todo_id2 == todo_id: res = date if cache is not None: cache['_calendar'][Todo.__name__]\ .setdefault(todo_id2, {}) cache['_calendar'][ Todo.__name__][todo_id2]['creationdate'] = date if res is not None: return res return super(Collection, cls).get_creationdate(uri, cache=cache)
def get_recent_sales(cls): """ Return sales of current channel, which were made within last 5 days and are in draft state. Sort by write_date or create_date of Sale and sale lines. """ SaleLine = Pool().get('sale.line') context = Transaction().context date = ( datetime.now() - timedelta(days=5) ).strftime('%Y-%m-%d %H:%M:%S') current_channel = context['current_channel'] SaleTable = cls.__table__() SaleLineTable = SaleLine.__table__() cursor = Transaction().cursor query = SaleTable.join( SaleLineTable, condition=(SaleTable.id == SaleLineTable.sale) ).select( SaleTable.id, where=( (SaleTable.channel == Literal(current_channel)) & (SaleTable.state.in_([ 'draft', 'quotation', 'confirmed', 'processing' ])) & ( (SaleTable.write_date >= Literal(date)) | (SaleTable.create_date >= Literal(date)) ) ), order_by=( SaleLineTable.write_date.desc, SaleLineTable.create_date.desc, SaleTable.write_date.desc, SaleTable.create_date.desc ) ) cursor.execute(*query) ids = [x[0] for x in cursor.fetchall()] return [cls(id).serialize('recent_sales') for id in ids]
def __register__(cls, module_name): configuration_h = backend.TableHandler(cls) Credential = Pool().get('document.signature.configuration') super().__register__(module_name) # Migration from coog 2.6 Link configuration to credential if configuration_h.column_exist('company'): table = cls.__table__() credential = Credential.__table__() cursor = Transaction().connection.cursor() cursor.execute(*credential.select(credential.id)) result = cursor.fetchone() if result is not None: credential_id = result[0] cursor.execute(*table.update(columns=[table.credential], values=[credential_id])) configuration_h.drop_column('company')
def get_creationdate(cls, uri, cache=None): Todo = Pool().get('calendar.todo') todo = Todo.__table__() cursor = Transaction().cursor calendar_id = cls.calendar(uri) if not calendar_id: calendar_id = cls.calendar(uri, ics=True) if calendar_id and (uri[10:].split('/', 1) + [None])[1]: todo_id = cls.todo(uri, calendar_id=calendar_id) if todo_id: if cache is not None: cache.setdefault('_calendar', {}) cache['_calendar'].setdefault(Todo.__name__, {}) ids = cache['_calendar'][Todo.__name__].keys() if todo_id not in ids: ids.append(todo_id) elif 'creationdate' in cache['_calendar'][ Todo.__name__][todo_id]: return cache['_calendar'][Todo.__name__][ todo_id]['creationdate'] else: ids = [todo_id] res = None for sub_ids in grouped_slice(ids): red_sql = reduce_ids(todo.id, sub_ids) cursor.execute(*todo.select(todo.id, Extract('EPOCH', todo.create_date), where=red_sql)) for todo_id2, date in cursor.fetchall(): if todo_id2 == todo_id: res = date if cache is not None: cache['_calendar'][Todo.__name__]\ .setdefault(todo_id2, {}) cache['_calendar'][Todo.__name__][ todo_id2]['creationdate'] = date if res is not None: return res return super(Collection, cls).get_creationdate(uri, cache=cache)
def get_lastmodified(cls, uri, cache=None): Todo = Pool().get('calendar.todo') todo = Todo.__table__() cursor = Transaction().cursor calendar_id = cls.calendar(uri) if calendar_id and (uri[10:].split('/', 1) + [None])[1]: todo_id = cls.todo(uri, calendar_id=calendar_id) if todo_id: if cache is not None: cache.setdefault('_calendar', {}) cache['_calendar'].setdefault(Todo.__name__, {}) ids = cache['_calendar'][Todo.__name__].keys() if todo_id not in ids: ids.append(todo_id) elif 'lastmodified' in cache['_calendar'][ Todo.__name__][todo_id]: return cache['_calendar'][Todo.__name__][ todo_id]['lastmodified'] else: ids = [todo_id] res = None for sub_ids in grouped_slice(ids, cursor.IN_MAX / 2): red_id_sql = reduce_ids(todo.id, sub_ids) red_parent_sql = reduce_ids(todo.parent, sub_ids) cursor.execute(*todo.select(Coalesce(todo.parent, todo.id), Max(Extract('EPOCH', Coalesce(todo.write_date, todo.create_date))), where=red_id_sql | red_parent_sql, group_by=(todo.parent, todo.id))) for todo_id2, date in cursor.fetchall(): if todo_id2 == todo_id: res = date if cache is not None: cache['_calendar'][Todo.__name__]\ .setdefault(todo_id2, {}) cache['_calendar'][Todo.__name__][ todo_id2]['lastmodified'] = date if res is not None: return res return super(Collection, cls).get_lastmodified(uri, cache=cache)
def __register__(cls, module_name): Identifier = Pool().get('party.identifier') cursor = Transaction().connection.cursor() sql_table = cls.__table__() identifier = Identifier.__table__() super(Party, cls).__register__(module_name) table = cls.__table_handler__(module_name) # Migration from 4.0: Move sepa_creditor_identifier to identifier if table.column_exist('sepa_creditor_identifier'): select = sql_table.select(Literal(0), CurrentTimestamp(), sql_table.id, Literal('sepa'), sql_table.sepa_creditor_identifier, where=((sql_table.sepa_creditor_identifier != Null) & (sql_table.sepa_creditor_identifier != ""))) cursor.execute(*identifier.insert( columns=[identifier.create_uid, identifier.create_date, identifier.party, identifier.type, identifier.code], values=select)) table.drop_column('sepa_creditor_identifier')
def table_query(self=None): price_list = Pool().get('price_master_datas.pricedata') PriceList = price_list.__table__() where = Literal(False) if Transaction().context.get('type') == '01': Product = Pool().get('product.product') drug_code = Transaction().context.get('drug_code') product_id = Product.search([('id', '=', drug_code)]) if product_id != []: where = Literal(True) product_id_price = product_id[0].id Price = price_list.search( [('retrieve_the_code', '=', product_id_price)], query=True, order=[]) where &= PriceList.id.in_(Price) if Transaction().context.get('type') == '00': condition = [] start_time = Transaction().context.get('start_time') end_time = Transaction().context.get('end_time') if start_time != None: condition.append(('effective_date', '>=', start_time), ) if end_time != None: condition.append(('effective_date', '<=', end_time), ) Price = price_list.search(condition) if Price != []: price_id = [] where = Literal(True) for i in Price: price_id.append(i.id) where &= PriceList.id.in_(price_id) Result = PriceList.select( PriceList.id.as_('id'), Max(PriceList.create_uid).as_('create_uid'), Max(PriceList.create_date).as_('create_date'), Max(PriceList.write_uid).as_('write_uid'), Max(PriceList.write_date).as_('write_date'), PriceList.drug_specifications.as_('drug_specifications'), where=where, group_by=PriceList.id) return Result
def __register__(cls, module_name): TableHandler = backend.get('TableHandler') cursor = Transaction().cursor Article = Pool().get('nereid.cms.article') table = TableHandler(cursor, Article, module_name) # Move data from category to categories if table.column_exist('category'): article = Article.__table__() article_categ_rel = cls.__table__() article_select = article.select(article.id, article.category) cursor.execute(*article_categ_rel.insert( columns=[article_categ_rel.article, article_categ_rel.category], values=article_select )) table.drop_column('category') super(ArticleCategoryRelation, cls).__register__(module_name)
def search_patient_status(cls, name, clause): p = Pool().get('gnuhealth.inpatient.registration') table = p.__table__() pat = cls.__table__() _, operator, value = clause # Validate operator and value if operator not in ['=', '!=']: raise ValueError('Wrong operator: %s' % operator) if value is not True and value is not False: raise ValueError('Wrong value: %s' % value) # Find hospitalized patient ids j = pat.join(table, condition=pat.id == table.patient) s = j.select(pat.id, where=table.state == 'hospitalized') # Choose domain operator if (operator == '=' and value) or (operator == '!=' and not value): d = 'in' else: d = 'not in' return [('id', d, s)]
def table_query(cls): Opportunity = Pool().get('sale.opportunity') opportunity = Opportunity.__table__() return opportunity.select( Max(opportunity.create_uid).as_('create_uid'), Max(opportunity.create_date).as_('create_date'), Max(opportunity.write_uid).as_('write_uid'), Max(opportunity.write_date).as_('write_date'), opportunity.company, Count(Literal(1)).as_('number'), Sum(Case((opportunity.state.in_(cls._converted_state()), Literal(1)), else_=Literal(0))).as_('converted'), Sum(Case((opportunity.state.in_(cls._won_state()), Literal(1)), else_=Literal(0))).as_('won'), Sum(Case((opportunity.state.in_(cls._lost_state()), Literal(1)), else_=Literal(0))).as_('lost'), Sum(opportunity.amount).as_('amount'), Sum(Case((opportunity.state.in_(cls._converted_state()), opportunity.amount), else_=Literal(0))).as_('converted_amount'), Sum(Case((opportunity.state.in_(cls._won_state()), opportunity.amount), else_=Literal(0))).as_('won_amount'))
def search_patient_status(cls, name, clause): p = Pool().get('gnuhealth.inpatient.registration') table = p.__table__() pat = cls.__table__() _, operator, value = clause # Validate operator and value if operator not in ['=', '!=']: raise ValueError('Wrong operator: %s' % operator) if value is not True and value is not False: raise ValueError('Wrong value: %s' % value) # Find hospitalized patient ids j = pat.join(table, condition = pat.id == table.patient) s = j.select(pat.id, where = table.state == 'hospitalized') # Choose domain operator if (operator == '=' and value) or (operator == '!=' and not value): d = 'in' else: d = 'not in' return [('id', d, s)]
def search_payment_days(cls, name, clause): Party = Pool().get('party.party') if backend.name == 'sqlite': # Sqlite does not support UNNEST function return ['OR', [ ('type', '=', 'out'), ('party.customer_payment_days',) + tuple(clause[1:]), ], [ ('type', '=', 'in'), ('party.supplier_payment_days',) + tuple(clause[1:]), ]] party = Party.__table__() _, operator, value = clause Operator = fields.SQL_OPERATORS[operator] customer_days = party.select(party.id, Unnest(RegExpSplitToArray(party.customer_payment_days, r'\s+')).as_('day')) customer_days = customer_days.select(customer_days.id, where=(Operator(Cast(NullIf(customer_days.day, ''), 'int'), value))) supplier_days = party.select(party.id, Unnest(RegExpSplitToArray(party.supplier_payment_days, r'\s+')).as_('day')) supplier_days = supplier_days.select(supplier_days.id, where=(Operator(Cast(NullIf(supplier_days.day, ''), 'int'), value))) return ['OR', [ ('type', '=', 'out'), ('party', 'in', customer_days), ], [ ('type', '=', 'in'), ('party', 'in', supplier_days), ]]
def __register__(cls, module_name): TimesheetWork = Pool().get('timesheet.work') TableHandler = backend.get('TableHandler') cursor = Transaction().cursor table_project_work = TableHandler(cursor, cls, module_name) table_timesheet_work = TableHandler(cursor, TimesheetWork, module_name) project = cls.__table__() timesheet = TimesheetWork.__table__() migrate_sequence = (not table_project_work.column_exist('sequence') and table_timesheet_work.column_exist('sequence')) super(Work, cls).__register__(module_name) # Migration from 2.0: copy sequence from timesheet to project if migrate_sequence: cursor.execute(*timesheet.join( project, condition=project.work == timesheet.id).select( timesheet.sequence, timesheet.id)) for sequence, id_ in cursor.fetchall(): cursor.execute(*project.update(columns=[project.sequence], values=[sequence], where=project.work == id_)) # Migration from 2.4: drop required on sequence table_project_work.not_null_action('sequence', action='remove') # Migration from 3.4: change effort into timedelta effort_duration if table_project_work.column_exist('effort'): cursor.execute(*project.select( project.id, project.effort, where=project.effort != Null)) for id_, effort in cursor.fetchall(): duration = datetime.timedelta(hours=effort) cursor.execute( *project.update([project.effort_duration], [duration], where=project.id == id_)) table_project_work.drop_column('effort')
def __register__(cls, module_name): super(Party, cls).__register__(module_name) PaymentProfile = Pool().get('party.payment_profile') TableHandler = backend.get('TableHandler') cursor = Transaction().cursor table = TableHandler(cursor, cls, module_name) party = cls.__table__() payment_profile = PaymentProfile.__table__() # Migration # Move the content of authorize_profile_id from party to # payment profiles and drop authorize_profile_id from party table if table.column_exist('authorize_profile_id'): update = payment_profile.update( columns=[payment_profile.authorize_profile_id], values=[party.authorize_profile_id], from_=[party], where=(payment_profile.party == party.id) ) cursor.execute(*update) table.drop_column('authorize_profile_id')
def get_creationdate(cls, uri, cache=None): Calendar = Pool().get('calendar.calendar') Event = Pool().get('calendar.event') calendar = Calendar.__table__() event = Event.__table__() calendar_id = cls.calendar(uri) if not calendar_id: calendar_id = cls.calendar(uri, ics=True) if calendar_id: if not (uri[10:].split('/', 1) + [None])[1]: if cache is not None: cache.setdefault('_calendar', {}) cache['_calendar'].setdefault(Calendar.__name__, {}) ids = cache['_calendar'][Calendar.__name__].keys() if calendar_id not in ids: ids.append(calendar_id) elif 'creationdate' in cache['_calendar'][ Calendar.__name__][calendar_id]: return cache['_calendar'][Calendar.__name__][ calendar_id]['creationdate'] else: ids = [calendar_id] res = None cursor = Transaction().cursor for sub_ids in grouped_slice(ids): red_sql = reduce_ids(calendar.id, sub_ids) cursor.execute(*calendar.select(calendar.id, Extract('EPOCH', calendar.create_date), where=red_sql)) for calendar_id2, date in cursor.fetchall(): if calendar_id2 == calendar_id: res = date if cache is not None: cache['_calendar'][Calendar.__name__]\ .setdefault(calendar_id2, {}) cache['_calendar'][Calendar.__name__][ calendar_id2]['creationdate'] = date if res is not None: return res else: event_id = cls.event(uri, calendar_id=calendar_id) if event_id: if cache is not None: cache.setdefault('_calendar', {}) cache['_calendar'].setdefault(Event.__name__, {}) ids = cache['_calendar'][Event.__name__].keys() if event_id not in ids: ids.append(event_id) elif 'creationdate' in cache['_calendar'][ Event.__name__][event_id]: return cache['_calendar'][Event.__name__][ event_id]['creationdate'] else: ids = [event_id] res = None cursor = Transaction().cursor for sub_ids in grouped_slice(ids): red_sql = reduce_ids(event.id, sub_ids) cursor.execute(*event.select(event.id, Extract('EPOCH', event.create_date), where=red_sql)) for event_id2, date in cursor.fetchall(): if event_id2 == event_id: res = date if cache is not None: cache['_calendar'][Event.__name__]\ .setdefault(event_id2, {}) cache['_calendar'][Event.__name__][ event_id2]['creationdate'] = date if res is not None: return res return super(Collection, cls).get_creationdate(uri, cache=cache)
def get_table_for_table_query(cls): Relation = Pool().get('party.relation') return Relation.__table__()
def _get_products(self): """ Return a query based on the node settings. This is separated for easy subclassing. The returned value would be a tuple with the dollowing elements: * The Model instance * Select query instance * The Table instance for the SQL Pagination """ Node = Pool().get('product.tree_node') Product = Pool().get('product.product') ProductTemplate = Pool().get('product.template') ProductNodeRelation = Pool().get('product.product-product.tree_node') ProductTable = Product.__table__() TemplateTable = ProductTemplate.__table__() RelTable = ProductNodeRelation.__table__() NodeTable = Node.__table__() if self.display == 'product.product': query = ProductTable.join( TemplateTable, condition=(TemplateTable.id == ProductTable.template) ).join( RelTable, condition=(RelTable.product == ProductTable.id) ).join( NodeTable, condition=(RelTable.node == NodeTable.id) ).select( where=( TemplateTable.active & ProductTable.displayed_on_eshop & ProductTable.active & (NodeTable.left >= Literal(self.left)) & (NodeTable.right <= Literal(self.right)) ), order_by=RelTable.sequence.asc ) return Product, query, ProductTable elif self.display == 'product.template': query = TemplateTable.join( ProductTable, condition=(TemplateTable.id == ProductTable.template) ).join( RelTable, condition=(RelTable.product == ProductTable.id) ).join( NodeTable, condition=(RelTable.node == NodeTable.id) ).select( where=( TemplateTable.active & ProductTable.displayed_on_eshop & ProductTable.active & (NodeTable.left >= Literal(self.left)) & (NodeTable.right <= Literal(self.right)) ), order_by=RelTable.sequence.asc ) return ProductTemplate, query, TemplateTable
def __register__(cls, module_name): TimesheetWork = Pool().get('timesheet.work') transaction = Transaction() cursor = transaction.connection.cursor() update = transaction.connection.cursor() table_project_work = cls.__table_handler__(module_name) project = cls.__table__() timesheet = TimesheetWork.__table__() work_exist = table_project_work.column_exist('work') add_parent = (not table_project_work.column_exist('parent') and work_exist) add_company = (not table_project_work.column_exist('company') and work_exist) add_name = (not table_project_work.column_exist('name') and work_exist) super(Work, cls).__register__(module_name) # Migration from 3.4: change effort into timedelta effort_duration if table_project_work.column_exist('effort'): cursor.execute(*project.select(project.id, project.effort, where=project.effort != Null)) for id_, effort in cursor: duration = datetime.timedelta(hours=effort) update.execute(*project.update( [project.effort_duration], [duration], where=project.id == id_)) table_project_work.drop_column('effort') # Migration from 3.6: add parent, company, drop required on work, # fill name if add_parent: second_project = cls.__table__() query = project.join(timesheet, condition=project.work == timesheet.id ).join(second_project, condition=timesheet.parent == second_project.work ).select(project.id, second_project.id) cursor.execute(*query) for id_, parent in cursor: update.execute(*project.update( [project.parent], [parent], where=project.id == id_)) cls._rebuild_tree('parent', None, 0) if add_company: cursor.execute(*project.join(timesheet, condition=project.work == timesheet.id ).select(project.id, timesheet.company)) for id_, company in cursor: update.execute(*project.update( [project.company], [company], where=project.id == id_)) table_project_work.not_null_action('work', action='remove') if add_name: cursor.execute(*project.join(timesheet, condition=project.work == timesheet.id ).select(project.id, timesheet.name)) for id_, name in cursor: update.execute(*project.update( [project.name], [name], where=project.id == id_)) # Migration from 4.0: remove work if work_exist: table_project_work.drop_constraint('work_uniq') cursor.execute(*project.select(project.id, project.work, where=project.work != Null)) for project_id, work_id in cursor: update.execute(*timesheet.update( [timesheet.origin, timesheet.name], ['%s,%s' % (cls.__name__, project_id), Null], where=timesheet.id == work_id)) table_project_work.drop_column('work') # Migration from 5.4: replace state by status table_project_work.not_null_action('state', action='remove') # Migration from 6.0: remove left and right table_project_work.drop_column('left') table_project_work.drop_column('right')
def __register__(cls, module_name): Party = Pool().get('party.party') Model = Pool().get('ir.model') ModelField = Pool().get('ir.model.field') Property = Pool().get('ir.property') PaymentProfile = Pool().get('party.payment_profile') TableHandler = backend.get('TableHandler') cursor = Transaction().cursor table = TableHandler(cursor, cls, module_name) migration_needed = False if not table.column_exist('credit_account'): migration_needed = True migrate_last_four_digits = False if not table.column_exist('last_four_digits'): migrate_last_four_digits = True super(PaymentTransaction, cls).__register__(module_name) if migration_needed and not Pool.test: # Migration # Set party's receivable account as the credit_account on # transactions transaction = cls.__table__() party = Party.__table__() property = Property.__table__() account_model, = Model.search([ ('model', '=', 'party.party'), ]) account_receivable_field, = ModelField.search([ ('model', '=', account_model.id), ('name', '=', 'account_receivable'), ('ttype', '=', 'many2one'), ]) update = transaction.update( columns=[transaction.credit_account], values=[ Trim( Substring(property.value, ',.*'), 'LEADING', ',' ).cast(cls.credit_account.sql_type().base) ], from_=[party, property], where=( transaction.party == party.id ) & ( property.res == Concat(Party.__name__ + ',', party.id) ) & ( property.field == account_receivable_field.id ) & ( property.company == transaction.company ) ) cursor.execute(*update) if migrate_last_four_digits and not Pool.test: transaction = cls.__table__() payment_profile = PaymentProfile.__table__() cursor.execute(*transaction.update( columns=[transaction.last_four_digits], values=[payment_profile.last_4_digits], from_=[payment_profile], where=(transaction.payment_profile == payment_profile.id) ))
def __register__(cls, module_name): TimesheetWork = Pool().get('timesheet.work') TableHandler = backend.get('TableHandler') cursor = Transaction().cursor table_project_work = TableHandler(cursor, cls, module_name) table_timesheet_work = TableHandler(cursor, TimesheetWork, module_name) project = cls.__table__() timesheet = TimesheetWork.__table__() migrate_sequence = (not table_project_work.column_exist('sequence') and table_timesheet_work.column_exist('sequence')) add_parent = not table_project_work.column_exist('parent') add_company = not table_project_work.column_exist('company') add_name = not table_project_work.column_exist('name') super(Work, cls).__register__(module_name) # Migration from 2.0: copy sequence from timesheet to project if migrate_sequence: cursor.execute(*timesheet.join(project, condition=project.work == timesheet.id ).select(timesheet.sequence, timesheet.id)) for sequence, id_ in cursor.fetchall(): cursor.execute(*project.update( columns=[project.sequence], values=[sequence], where=project.work == id_)) # Migration from 2.4: drop required on sequence table_project_work.not_null_action('sequence', action='remove') # Migration from 3.4: change effort into timedelta effort_duration if table_project_work.column_exist('effort'): cursor.execute(*project.select(project.id, project.effort, where=project.effort != Null)) for id_, effort in cursor.fetchall(): duration = datetime.timedelta(hours=effort) cursor.execute(*project.update( [project.effort_duration], [duration], where=project.id == id_)) table_project_work.drop_column('effort') # Migration from 3.6: add parent, company, drop required on work, # fill name if add_parent: second_project = cls.__table__() query = project.join(timesheet, condition=project.work == timesheet.id ).join(second_project, condition=timesheet.parent == second_project.work ).select(project.id, second_project.id) cursor.execute(*query) for id_, parent in cursor.fetchall(): cursor.execute(*project.update( [project.parent], [parent], where=project.id == id_)) cls._rebuild_tree('parent', None, 0) if add_company: cursor.execute(*project.join(timesheet, condition=project.work == timesheet.id ).select(project.id, timesheet.company)) for id_, company in cursor.fetchall(): cursor.execute(*project.update( [project.company], [company], where=project.id == id_)) table_project_work.not_null_action('work', action='remove') if add_name: cursor.execute(*project.join(timesheet, condition=project.work == timesheet.id ).select(project.id, timesheet.name)) for id_, name in cursor.fetchall(): cursor.execute(*project.update( [project.name], [name], where=project.id == id_))