diff --git a/addons/account/__init__.py b/addons/account/__init__.py index 3d6f6061a72..15a3bc81cf4 100644 --- a/addons/account/__init__.py +++ b/addons/account/__init__.py @@ -32,7 +32,6 @@ import account_financial_report import wizard import report import product -import ir_sequence import company import res_currency import edi diff --git a/addons/account/__openerp__.py b/addons/account/__openerp__.py index 45c02f2f2d4..77bbdc394f5 100644 --- a/addons/account/__openerp__.py +++ b/addons/account/__openerp__.py @@ -107,7 +107,6 @@ for a particular financial year and for preparation of vouchers there is a modul 'product_view.xml', 'account_assert_test.xml', 'account_analytic_view.xml', - 'ir_sequence_view.xml', 'company_view.xml', 'edi/invoice_action_data.xml', 'account_bank_view.xml', diff --git a/addons/account/account.py b/addons/account/account.py index d4c34f49922..555d54c3ece 100644 --- a/addons/account/account.py +++ b/addons/account/account.py @@ -812,7 +812,8 @@ class account_journal(osv.osv): 'implementation':'no_gap', 'prefix': prefix + "/%(year)s/", 'padding': 4, - 'number_increment': 1 + 'number_increment': 1, + 'use_date_range': True, } if 'company_id' in vals: seq['company_id'] = vals['company_id'] @@ -1631,7 +1632,7 @@ class account_move_reconcile(osv.osv): 'opening_reconciliation': fields.boolean('Opening Entries Reconciliation', help="Is this reconciliation produced by the opening of a new fiscal year ?."), } _defaults = { - 'name': lambda self,cr,uid,ctx=None: self.pool.get('ir.sequence').get(cr, uid, 'account.reconcile', context=ctx) or '/', + 'name': lambda self,cr,uid,ctx=None: self.pool.get('ir.sequence').next_by_code(cr, uid, 'account.reconcile', context=ctx) or '/', } # You cannot unlink a reconciliation if it is a opening_reconciliation one, diff --git a/addons/account/ir_sequence.py b/addons/account/ir_sequence.py deleted file mode 100644 index 19d7ee0cf87..00000000000 --- a/addons/account/ir_sequence.py +++ /dev/null @@ -1,60 +0,0 @@ -# -*- coding: utf-8 -*- -############################################################################## -# -# OpenERP, Open Source Management Solution -# Copyright (C) 2004-2010 Tiny SPRL (). -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU Affero General Public License as -# published by the Free Software Foundation, either version 3 of the -# License, or (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Affero General Public License for more details. -# -# You should have received a copy of the GNU Affero General Public License -# along with this program. If not, see . -# -############################################################################## -from openerp import api -from openerp.osv import fields, osv - -class ir_sequence_fiscalyear(osv.osv): - _name = 'account.sequence.fiscalyear' - _rec_name = "sequence_main_id" - _columns = { - "sequence_id": fields.many2one("ir.sequence", 'Sequence', required=True, - ondelete='cascade'), - "sequence_main_id": fields.many2one("ir.sequence", 'Main Sequence', - required=True, ondelete='cascade'), - "fiscalyear_id": fields.many2one('account.fiscalyear', 'Fiscal Year', - required=True, ondelete='cascade') - } - - _sql_constraints = [ - ('main_id', 'CHECK (sequence_main_id != sequence_id)', - 'Main Sequence must be different from current !'), - ] - - -class ir_sequence(osv.osv): - _inherit = 'ir.sequence' - _columns = { - 'fiscal_ids': fields.one2many('account.sequence.fiscalyear', - 'sequence_main_id', 'Sequences', copy=True) - } - - @api.cr_uid_ids_context - def _next(self, cr, uid, seq_ids, context=None): - if context is None: - context = {} - for seq in self.browse(cr, uid, seq_ids, context): - for line in seq.fiscal_ids: - if line.fiscalyear_id.id == context.get('fiscalyear_id'): - return super(ir_sequence, self)._next(cr, uid, [line.sequence_id.id], context) - return super(ir_sequence, self)._next(cr, uid, seq_ids, context) - - -# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/account/ir_sequence_view.xml b/addons/account/ir_sequence_view.xml deleted file mode 100644 index bae969ed199..00000000000 --- a/addons/account/ir_sequence_view.xml +++ /dev/null @@ -1,27 +0,0 @@ - - - - - ir.sequence.form - ir.sequence - - - - - - - - - -
- - - - -
-
-
-
- -
-
diff --git a/addons/account/security/ir.model.access.csv b/addons/account/security/ir.model.access.csv index d35d227c869..b68d6e3f0a1 100644 --- a/addons/account/security/ir.model.access.csv +++ b/addons/account/security/ir.model.access.csv @@ -62,7 +62,6 @@ access_account_fiscal_position_account,account.fiscal.position all,model_account access_account_fiscal_position_template,account.fiscal.position.template,model_account_fiscal_position_template,account.group_account_manager,1,1,1,1 access_account_fiscal_position_tax_template,account.fiscal.position.tax.template,model_account_fiscal_position_tax_template,account.group_account_manager,1,1,1,1 access_account_fiscal_position_account_template,account.fiscal.position.account.template,model_account_fiscal_position_account_template,account.group_account_manager,1,1,1,1 -access_account_sequence_fiscal_year_user,account.sequence.fiscalyear user,model_account_sequence_fiscalyear,base.group_user,1,0,0,0 access_temp_range,temp.range,model_temp_range,account.group_account_manager,1,0,0,0 access_report_aged_receivable,report.aged.receivable,model_report_aged_receivable,account.group_account_manager,1,1,1,1 access_report_invoice_created,report.invoice.created,model_report_invoice_created,account.group_account_manager,1,1,1,1 @@ -88,12 +87,9 @@ access_account_account_invoice,account.account invoice,model_account_account,acc access_account_analytic_accountant,account.analytic.account accountant,analytic.model_account_analytic_account,account.group_account_user,1,1,1,1 access_account_account_type_invoice,account.account.type invoice,model_account_account_type,account.group_account_invoice,1,1,1,1 access_report_account_receivable_invoice,report.account.receivable.invoice,model_report_account_receivable,account.group_account_invoice,1,1,1,1 -access_account_sequence_fiscal_year_invoice,account.sequence.fiscalyear invoice,model_account_sequence_fiscalyear,account.group_account_invoice,1,1,1,1 access_account_tax_sale_manager,account.tax sale manager,model_account_tax,base.group_sale_salesman,1,0,0,0 access_account_journal_sale_manager,account.journal sale manager,model_account_journal,base.group_sale_salesman,1,0,0,0 access_account_invoice_tax_sale_manager,account.invoice.tax sale manager,model_account_invoice_tax,base.group_sale_salesman,1,0,0,0 -access_account_sequence_fiscal_year_sale_user,account.sequence.fiscalyear.sale.user,model_account_sequence_fiscalyear,base.group_sale_salesman,1,1,1,0 -access_account_sequence_fiscal_year_sale_manager,account.sequence.fiscalyear.sale.manager,model_account_sequence_fiscalyear,base.group_sale_manager,1,1,1,1 access_account_treasury_report_manager,account.treasury.report.manager,model_account_treasury_report,account.group_account_manager,1,0,0,0 access_account_financial_report,account.financial.report,model_account_financial_report,account.group_account_user,1,1,1,1 access_account_financial_report_invoice,account.financial.report invoice,model_account_financial_report,account.group_account_invoice,1,0,0,0 diff --git a/addons/account_asset/account_asset.py b/addons/account_asset/account_asset.py index 7aa97bb012e..ab8b1f9bd6a 100644 --- a/addons/account_asset/account_asset.py +++ b/addons/account_asset/account_asset.py @@ -280,7 +280,7 @@ class account_asset_asset(osv.osv): 'salvage_value': fields.float('Salvage Value', digits_compute=dp.get_precision('Account'), help="It is the amount you plan to have that you cannot depreciate.", readonly=True, states={'draft':[('readonly',False)]}), } _defaults = { - 'code': lambda obj, cr, uid, context: obj.pool.get('ir.sequence').get(cr, uid, 'account.asset.code'), + 'code': lambda obj, cr, uid, context: obj.pool.get('ir.sequence').next_by_code(cr, uid, 'account.asset.code'), 'purchase_date': lambda obj, cr, uid, context: time.strftime('%Y-%m-%d'), 'active': True, 'state': 'draft', diff --git a/addons/account_bank_statement_extensions/account_bank_statement.py b/addons/account_bank_statement_extensions/account_bank_statement.py index 72c3320be38..e0e6e768aae 100644 --- a/addons/account_bank_statement_extensions/account_bank_statement.py +++ b/addons/account_bank_statement_extensions/account_bank_statement.py @@ -82,7 +82,7 @@ class account_bank_statement_line_global(osv.osv): } _rec_name = 'code' _defaults = { - 'code': lambda s,c,u,ctx={}: s.pool.get('ir.sequence').get(c, u, 'account.bank.statement.line.global'), + 'code': lambda s,c,u,ctx={}: s.pool.get('ir.sequence').next_by_code(c, u, 'account.bank.statement.line.global'), 'name': '/', } _sql_constraints = [ diff --git a/addons/account_payment/account_payment.py b/addons/account_payment/account_payment.py index de72960a9c6..e5dbbd1b8cb 100644 --- a/addons/account_payment/account_payment.py +++ b/addons/account_payment/account_payment.py @@ -113,7 +113,7 @@ class payment_order(osv.osv): 'state': 'draft', 'date_prefered': 'due', 'date_created': lambda *a: time.strftime('%Y-%m-%d'), - 'reference': lambda self,cr,uid,context: self.pool.get('ir.sequence').get(cr, uid, 'payment.order'), + 'reference': lambda self,cr,uid,context: self.pool.get('ir.sequence').next_by_code(cr, uid, 'payment.order'), } def set_to_draft(self, cr, uid, ids, *args): @@ -126,7 +126,7 @@ class payment_order(osv.osv): for order in self.read(cr, uid, ids, ['reference']): if not order['reference']: - reference = ir_seq_obj.get(cr, uid, 'payment.order') + reference = ir_seq_obj.next_by_code(cr, uid, 'payment.order') self.write(cr, uid, order['id'], {'reference':reference}) return True @@ -322,7 +322,7 @@ class payment_line(osv.osv): } _defaults = { 'name': lambda obj, cursor, user, context: obj.pool.get('ir.sequence' - ).get(cursor, user, 'payment.line'), + ).next_by_code(cursor, user, 'payment.line'), 'state': 'normal', 'currency': _get_currency, 'company_currency': _get_currency, diff --git a/addons/analytic/models/analytic.py b/addons/analytic/models/analytic.py index 6d01a68c9a3..6d7423d1adf 100644 --- a/addons/analytic/models/analytic.py +++ b/addons/analytic/models/analytic.py @@ -251,7 +251,7 @@ class account_analytic_account(osv.osv): _defaults = { 'type': 'normal', 'company_id': _default_company, - 'code' : lambda obj, cr, uid, context: obj.pool.get('ir.sequence').get(cr, uid, 'account.analytic.account'), + 'code' : lambda obj, cr, uid, context: obj.pool.get('ir.sequence').next_by_code(cr, uid, 'account.analytic.account'), 'state': 'open', 'user_id': lambda self, cr, uid, ctx: uid, 'partner_id': lambda self, cr, uid, ctx: ctx.get('partner_id', False), diff --git a/addons/hr_payroll/hr_payroll.py b/addons/hr_payroll/hr_payroll.py index 397938f3442..cda5cc657c0 100644 --- a/addons/hr_payroll/hr_payroll.py +++ b/addons/hr_payroll/hr_payroll.py @@ -377,7 +377,7 @@ class hr_payslip(osv.osv): slip_line_pool = self.pool.get('hr.payslip.line') sequence_obj = self.pool.get('ir.sequence') for payslip in self.browse(cr, uid, ids, context=context): - number = payslip.number or sequence_obj.get(cr, uid, 'salary.slip') + number = payslip.number or sequence_obj.next_by_code(cr, uid, 'salary.slip') #delete old payslip lines old_slipline_ids = slip_line_pool.search(cr, uid, [('slip_id', '=', payslip.id)], context=context) # old_slipline_ids diff --git a/addons/l10n_be/wizard/l10n_be_partner_vat_listing.py b/addons/l10n_be/wizard/l10n_be_partner_vat_listing.py index 8fa11545dee..32a6d1c0125 100644 --- a/addons/l10n_be/wizard/l10n_be_partner_vat_listing.py +++ b/addons/l10n_be/wizard/l10n_be_partner_vat_listing.py @@ -174,7 +174,7 @@ class partner_vat_list(osv.osv_memory): obj_users = self.pool.get('res.users') obj_partner = self.pool.get('res.partner') obj_model_data = self.pool.get('ir.model.data') - seq_declarantnum = obj_sequence.get(cr, uid, 'declarantnum') + seq_declarantnum = obj_sequence.next_by_code(cr, uid, 'declarantnum') obj_cmpny = obj_users.browse(cr, uid, uid, context=context).company_id company_vat = obj_cmpny.partner_id.vat @@ -184,7 +184,7 @@ class partner_vat_list(osv.osv_memory): company_vat = company_vat.replace(' ','').upper() SenderId = company_vat[2:] issued_by = company_vat[:2] - seq_declarantnum = obj_sequence.get(cr, uid, 'declarantnum') + seq_declarantnum = obj_sequence.next_by_code(cr, uid, 'declarantnum') dnum = company_vat[2:] + seq_declarantnum[-4:] street = city = country = '' addr = obj_partner.address_get(cr, uid, [obj_cmpny.partner_id.id], ['invoice']) diff --git a/addons/l10n_be/wizard/l10n_be_vat_intra.py b/addons/l10n_be/wizard/l10n_be_vat_intra.py index 386aa0906fd..f937632cb51 100644 --- a/addons/l10n_be/wizard/l10n_be_vat_intra.py +++ b/addons/l10n_be/wizard/l10n_be_vat_intra.py @@ -123,7 +123,7 @@ class partner_vat_intra(osv.osv_memory): if not p_id_list: raise osv.except_osv(_('Insufficient Data!'),_('No partner has a VAT number associated with him.')) - seq_declarantnum = obj_sequence.get(cr, uid, 'declarantnum') + seq_declarantnum = obj_sequence.next_by_code(cr, uid, 'declarantnum') dnum = company_vat[2:] + seq_declarantnum[-4:] addr = obj_partner.address_get(cr, uid, [data_company.partner_id.id], ['invoice']) diff --git a/addons/l10n_in_hr_payroll/l10n_in_hr_payroll.py b/addons/l10n_in_hr_payroll/l10n_in_hr_payroll.py index 0af3535bfd0..1c2402153d0 100644 --- a/addons/l10n_in_hr_payroll/l10n_in_hr_payroll.py +++ b/addons/l10n_in_hr_payroll/l10n_in_hr_payroll.py @@ -132,7 +132,7 @@ class payroll_advice(osv.osv): raise osv.except_osv(_('Error!'), _('You can not confirm Payment advice without advice lines.')) advice_date = datetime.strptime(advice.date, DATETIME_FORMAT) advice_year = advice_date.strftime('%m') + '-' + advice_date.strftime('%Y') - number = seq_obj.get(cr, uid, 'payment.advice') + number = seq_obj.next_by_code(cr, uid, 'payment.advice') sequence_num = 'PAY' + '/' + advice_year + '/' + number self.write(cr, uid, [advice.id], {'number': sequence_num, 'state': 'confirm'}, context=context) return True diff --git a/addons/mrp/mrp.py b/addons/mrp/mrp.py index 914cfc376a6..9b3d832c541 100644 --- a/addons/mrp/mrp.py +++ b/addons/mrp/mrp.py @@ -585,7 +585,7 @@ class mrp_production(osv.osv): 'date_planned': lambda *a: time.strftime('%Y-%m-%d %H:%M:%S'), 'product_qty': lambda *a: 1.0, 'user_id': lambda self, cr, uid, c: uid, - 'name': lambda x, y, z, c: x.pool.get('ir.sequence').get(y, z, 'mrp.production') or '/', + 'name': lambda x, y, z, c: x.pool.get('ir.sequence').next_by_code(y, z, 'mrp.production') or '/', 'company_id': lambda self, cr, uid, c: self.pool.get('res.company')._company_default_get(cr, uid, 'mrp.production', context=c), 'location_src_id': _src_id_default, 'location_dest_id': _dest_id_default diff --git a/addons/mrp/security/ir.model.access.csv b/addons/mrp/security/ir.model.access.csv index 7ed5ff7596e..fc3b228bb48 100644 --- a/addons/mrp/security/ir.model.access.csv +++ b/addons/mrp/security/ir.model.access.csv @@ -28,7 +28,6 @@ access_mrp_production_stock_worker,mrp.production stock_worker,model_mrp_product access_report_workcenter_load,report.workcenter.load,model_report_workcenter_load,mrp.group_mrp_manager,1,1,1,1 access_report_mrp_inout,report.mrp.inout,model_report_mrp_inout,mrp.group_mrp_manager,1,1,1,1 access_ir_property_manager,ir.property manager,base.model_ir_property,mrp.group_mrp_manager,1,1,1,1 -access_account_sequence_fiscalyear,account.sequence.fiscalyear,account.model_account_sequence_fiscalyear,mrp.group_mrp_user,1,1,1,1 access_product_product_user,product.product user,product.model_product_product,mrp.group_mrp_user,1,0,0,0 access_product_template_user,product.template user,product.model_product_template,mrp.group_mrp_user,1,0,0,0 access_product_uom_user,product.uom user,product.model_product_uom,mrp.group_mrp_user,1,0,0,0 @@ -42,14 +41,12 @@ access_resource_calendar_attendance_manager,mrp.resource.calendar.attendance.man access_product_puom_categ,product.uom.categ,product.model_product_uom_categ,mrp.group_mrp_user,1,0,0,0 access_resource_resource,resource.resource,resource.model_resource_resource,mrp.group_mrp_user,1,0,0,0 access_board_board_user,mrp.board.board,board.model_board_board,mrp.group_mrp_user,1,0,0,0 -access_account_sequence_fiscalyear_manager,account.sequence.fiscalyear,account.model_account_sequence_fiscalyear,mrp.group_mrp_manager,1,0,0,0 access_product_supplierinfo_manager,product.supplierinfo user,product.model_product_supplierinfo,mrp.group_mrp_manager,1,0,0,0 access_mrp_production_manager,mrp.production manager,model_mrp_production,mrp.group_mrp_manager,1,0,0,0 access_procurement_manager,procurement.order,model_procurement_order,mrp.group_mrp_manager,1,0,0,0 access_workcenter_manager,mrp.production.workcenter.line,model_mrp_production_workcenter_line,mrp.group_mrp_manager,1,0,0,0 access_stock_move_mrp_manager,stock.move mrp_manager,stock.model_stock_move,mrp.group_mrp_manager,1,0,0,0 access_mrp_production_product_line_manager,mrp.production.product.line manager,model_mrp_production_product_line,mrp.group_mrp_manager,1,0,0,0 -access_account_sequence_fiscalyear_system,account.sequence.fiscalyear.system,account.model_account_sequence_fiscalyear,mrp.group_mrp_manager,1,0,0,0 access_stock_production_lot_user,stock.production.lot,stock.model_stock_production_lot,mrp.group_mrp_user,1,1,1,1 access_stock_warehouse_orderpoint_user,stock.warehouse.orderpoint,stock.model_stock_warehouse_orderpoint,mrp.group_mrp_user,1,0,0,0 access_stock_picking_mrp_manager,stock.picking mrp_manager,stock.model_stock_picking,mrp.group_mrp_manager,1,0,0,0 diff --git a/addons/mrp_repair/mrp_repair.py b/addons/mrp_repair/mrp_repair.py index d8c8925b24f..d80338fd024 100644 --- a/addons/mrp_repair/mrp_repair.py +++ b/addons/mrp_repair/mrp_repair.py @@ -187,7 +187,7 @@ class mrp_repair(osv.osv): _defaults = { 'state': lambda *a: 'draft', - 'name': lambda obj, cr, uid, context: obj.pool.get('ir.sequence').get(cr, uid, 'mrp.repair'), + 'name': lambda obj, cr, uid, context: obj.pool.get('ir.sequence').next_by_code(cr, uid, 'mrp.repair'), 'invoice_method': lambda *a: 'none', 'company_id': lambda self, cr, uid, context: self.pool.get('res.company')._company_default_get(cr, uid, 'mrp.repair', context=context), 'pricelist_id': lambda self, cr, uid, context: self.pool.get('product.pricelist').search(cr, uid, [('type', '=', 'sale')])[0], diff --git a/addons/point_of_sale/point_of_sale.py b/addons/point_of_sale/point_of_sale.py index 91e2cd14d09..5b67bdc9c1c 100644 --- a/addons/point_of_sale/point_of_sale.py +++ b/addons/point_of_sale/point_of_sale.py @@ -425,7 +425,7 @@ class pos_session(osv.osv): bank_statement_ids.append(statement_id) values.update({ - 'name': self.pool['ir.sequence'].get(cr, uid, 'pos.session'), + 'name': self.pool['ir.sequence'].next_by_code(cr, uid, 'pos.session'), 'statement_ids' : [(6, 0, bank_statement_ids)], 'config_id': config_id }) @@ -749,7 +749,7 @@ class pos_order(osv.osv): values['name'] = session.config_id.sequence_id._next() else: # fallback on any pos.order sequence - values['name'] = self.pool.get('ir.sequence').get_id(cr, uid, 'pos.order', 'code', context=context) + values['name'] = self.pool.get('ir.sequence').next_by_code(cr, uid, 'pos.order', context=context) return super(pos_order, self).create(cr, uid, values, context=context) def test_paid(self, cr, uid, ids, context=None): @@ -1322,7 +1322,7 @@ class pos_order_line(osv.osv): } _defaults = { - 'name': lambda obj, cr, uid, context: obj.pool.get('ir.sequence').get(cr, uid, 'pos.order.line'), + 'name': lambda obj, cr, uid, context: obj.pool.get('ir.sequence').next_by_code(cr, uid, 'pos.order.line'), 'qty': lambda *a: 1, 'discount': lambda *a: 0.0, 'company_id': lambda self,cr,uid,c: self.pool.get('res.users').browse(cr, uid, uid, c).company_id.id, diff --git a/addons/point_of_sale/security/ir.model.access.csv b/addons/point_of_sale/security/ir.model.access.csv index faa14f1d490..4850bf7321e 100644 --- a/addons/point_of_sale/security/ir.model.access.csv +++ b/addons/point_of_sale/security/ir.model.access.csv @@ -47,7 +47,6 @@ access_account_bank_statement_line_manager,account.bank.statement.line manager,a access_account_invoice_manager,account.invoice manager,account.model_account_invoice,group_pos_manager,1,1,1,1 access_product_product_supplierinfo_user,product.supplierinfo user,product.model_product_supplierinfo,group_pos_user,1,0,0,0 access_product_product_packaging_user,product.packaging user,product.model_product_packaging,group_pos_user,1,0,0,0 -access_account_sequence_fiscalyear_manager,account.sequence.fiscalyear manager,account.model_account_sequence_fiscalyear,group_pos_manager,1,0,0,0 access_stock_warehouse_manager,stock.warehouse manager,stock.model_stock_warehouse,group_pos_manager,1,0,0,0 access_stock_location_manager,stock.location manager,stock.model_stock_location,group_pos_manager,1,0,0,0 access_product_uom_manager,product.uom manager,product.model_product_uom,group_pos_manager,1,1,1,1 diff --git a/addons/procurement/procurement.py b/addons/procurement/procurement.py index 12d40a39be1..12e731e2e5c 100644 --- a/addons/procurement/procurement.py +++ b/addons/procurement/procurement.py @@ -64,7 +64,7 @@ class procurement_group(osv.osv): 'procurement_ids': fields.one2many('procurement.order', 'group_id', 'Procurements'), } _defaults = { - 'name': lambda self, cr, uid, c: self.pool.get('ir.sequence').get(cr, uid, 'procurement.group') or '', + 'name': lambda self, cr, uid, c: self.pool.get('ir.sequence').next_by_code(cr, uid, 'procurement.group') or '', 'move_type': lambda self, cr, uid, c: 'direct' } diff --git a/addons/purchase/purchase.py b/addons/purchase/purchase.py index 5dd100c6905..9f3622cb811 100644 --- a/addons/purchase/purchase.py +++ b/addons/purchase/purchase.py @@ -326,7 +326,7 @@ class purchase_order(osv.osv): def create(self, cr, uid, vals, context=None): if vals.get('name','/')=='/': - vals['name'] = self.pool.get('ir.sequence').get(cr, uid, 'purchase.order') or '/' + vals['name'] = self.pool.get('ir.sequence').next_by_code(cr, uid, 'purchase.order') or '/' context = dict(context or {}, mail_create_nolog=True) order = super(purchase_order, self).create(cr, uid, vals, context=context) self.message_post(cr, uid, [order], body=_("RFQ created"), context=context) @@ -1358,7 +1358,7 @@ class procurement_order(osv.osv): po_line_id = po_line_obj.create(cr, SUPERUSER_ID, line_vals, context=context) linked_po_ids.append(procurement.id) else: - name = seq_obj.get(cr, uid, 'purchase.order') or _('PO: %s') % procurement.name + name = seq_obj.next_by_code(cr, uid, 'purchase.order') or _('PO: %s') % procurement.name po_vals = { 'name': name, 'origin': procurement.origin, diff --git a/addons/purchase/security/ir.model.access.csv b/addons/purchase/security/ir.model.access.csv index 74a3e44ae05..b6f63a9bd46 100644 --- a/addons/purchase/security/ir.model.access.csv +++ b/addons/purchase/security/ir.model.access.csv @@ -28,7 +28,6 @@ access_account_invoice_purchase_manager,account_invoice purchase manager,account access_account_invoice_line_purchase_manager,account_invoice.line purchase manager,account.model_account_invoice_line,group_purchase_manager,1,0,0,0 access_account_invoice_tax_purchase,account_invoice.tax purchase,account.model_account_invoice_tax,group_purchase_user,1,1,1,1 access_account_fiscal_position_purchase_user,account.fiscal.position purchase,account.model_account_fiscal_position,group_purchase_user,1,0,0,0 -access_account_sequence_fiscalyear_purchase_user,account.sequence.fiscalyear purchase,account.model_account_sequence_fiscalyear,group_purchase_user,1,1,1,1 access_res_partner_purchase_user,res.partner purchase,base.model_res_partner,group_purchase_user,1,0,0,0 access_account_journal_period,account.journal.period,account.model_account_journal_period,group_purchase_user,1,1,1,0 access_account_journal,account.journal,account.model_account_journal,group_purchase_user,1,0,0,0 diff --git a/addons/purchase_requisition/purchase_requisition.py b/addons/purchase_requisition/purchase_requisition.py index 5af69a65a99..cfedba1a6b3 100644 --- a/addons/purchase_requisition/purchase_requisition.py +++ b/addons/purchase_requisition/purchase_requisition.py @@ -72,7 +72,7 @@ class purchase_requisition(osv.osv): 'exclusive': 'multiple', 'company_id': lambda self, cr, uid, c: self.pool.get('res.company')._company_default_get(cr, uid, 'purchase.requisition', context=c), 'user_id': lambda self, cr, uid, c: self.pool.get('res.users').browse(cr, uid, uid, c).id, - 'name': lambda obj, cr, uid, context: obj.pool.get('ir.sequence').get(cr, uid, 'purchase.order.requisition'), + 'name': lambda obj, cr, uid, context: obj.pool.get('ir.sequence').next_by_code(cr, uid, 'purchase.order.requisition'), 'picking_type_id': _get_picking_in, } diff --git a/addons/sale/sale.py b/addons/sale/sale.py index 2cbc975ae4c..c87a880891a 100644 --- a/addons/sale/sale.py +++ b/addons/sale/sale.py @@ -349,7 +349,7 @@ class sale_order(osv.osv): if context is None: context = {} if vals.get('name', '/') == '/': - vals['name'] = self.pool.get('ir.sequence').get(cr, uid, 'sale.order') or '/' + vals['name'] = self.pool.get('ir.sequence').next_by_code(cr, uid, 'sale.order') or '/' if vals.get('partner_id') and any(f not in vals for f in ['partner_invoice_id', 'partner_shipping_id', 'pricelist_id', 'fiscal_position']): defaults = self.onchange_partner_id(cr, uid, [], vals['partner_id'], context=context)['value'] if not vals.get('fiscal_position') and vals.get('partner_shipping_id'): diff --git a/addons/stock/stock.py b/addons/stock/stock.py index 75def9b40d1..d0293f159d6 100644 --- a/addons/stock/stock.py +++ b/addons/stock/stock.py @@ -681,7 +681,7 @@ class stock_picking(osv.osv): if ('name' not in vals) or (vals.get('name') in ('/', False)): ptype_id = vals.get('picking_type_id', context.get('default_picking_type_id', False)) sequence_id = self.pool.get('stock.picking.type').browse(cr, user, ptype_id, context=context).sequence_id.id - vals['name'] = self.pool.get('ir.sequence').get_id(cr, user, sequence_id, 'id', context=context) + vals['name'] = self.pool.get('ir.sequence').next_by_id(cr, user, sequence_id, context=context) return super(stock_picking, self).create(cr, user, vals, context) def _state_get(self, cr, uid, ids, field_name, arg, context=None): @@ -1486,7 +1486,7 @@ class stock_production_lot(osv.osv): 'create_date': fields.datetime('Creation Date'), } _defaults = { - 'name': lambda x, y, z, c: x.pool.get('ir.sequence').get(y, z, 'stock.lot.serial'), + 'name': lambda x, y, z, c: x.pool.get('ir.sequence').next_by_code(y, z, 'stock.lot.serial'), 'product_id': lambda x, y, z, c: c.get('product_id', False), } _sql_constraints = [ @@ -3692,7 +3692,7 @@ class stock_package(osv.osv): }, readonly=True, select=True), } _defaults = { - 'name': lambda self, cr, uid, context: self.pool.get('ir.sequence').get(cr, uid, 'stock.quant.package') or _('Unknown Pack') + 'name': lambda self, cr, uid, context: self.pool.get('ir.sequence').next_by_code(cr, uid, 'stock.quant.package') or _('Unknown Pack') } def _check_location_constraint(self, cr, uid, packs, context=None): @@ -4087,7 +4087,7 @@ class stock_warehouse_orderpoint(osv.osv): 'active': lambda *a: 1, 'logic': lambda *a: 'max', 'qty_multiple': lambda *a: 1, - 'name': lambda self, cr, uid, context: self.pool.get('ir.sequence').get(cr, uid, 'stock.orderpoint') or '', + 'name': lambda self, cr, uid, context: self.pool.get('ir.sequence').next_by_code(cr, uid, 'stock.orderpoint') or '', 'product_uom': lambda self, cr, uid, context: context.get('product_uom', False), 'company_id': lambda self, cr, uid, context: self.pool.get('res.company')._company_default_get(cr, uid, 'stock.warehouse.orderpoint', context=context) } diff --git a/addons/stock_landed_costs/stock_landed_costs.py b/addons/stock_landed_costs/stock_landed_costs.py index ad729377fb2..515fd2c1feb 100644 --- a/addons/stock_landed_costs/stock_landed_costs.py +++ b/addons/stock_landed_costs/stock_landed_costs.py @@ -93,7 +93,7 @@ class stock_landed_cost(osv.osv): } _defaults = { - 'name': lambda obj, cr, uid, context: obj.pool.get('ir.sequence').get(cr, uid, 'stock.landed.cost'), + 'name': lambda obj, cr, uid, context: obj.pool.get('ir.sequence').next_by_code(cr, uid, 'stock.landed.cost'), 'state': 'draft', 'date': fields.date.context_today, } diff --git a/addons/stock_picking_wave/stock_picking_wave.py b/addons/stock_picking_wave/stock_picking_wave.py index 48779f6882c..86809a8d58f 100644 --- a/addons/stock_picking_wave/stock_picking_wave.py +++ b/addons/stock_picking_wave/stock_picking_wave.py @@ -44,7 +44,7 @@ class stock_picking_wave(osv.osv): def create(self, cr, uid, vals, context=None): if vals.get('name', '/') == '/': - vals['name'] = self.pool.get('ir.sequence').get(cr, uid, 'picking.wave') or '/' + vals['name'] = self.pool.get('ir.sequence').next_by_code(cr, uid, 'picking.wave') or '/' return super(stock_picking_wave, self).create(cr, uid, vals, context=context) def done(self, cr, uid, ids, context=None): diff --git a/openerp/addons/base/ir/ir_sequence.py b/openerp/addons/base/ir/ir_sequence.py index d2296526394..36970310d92 100644 --- a/openerp/addons/base/ir/ir_sequence.py +++ b/openerp/addons/base/ir/ir_sequence.py @@ -18,33 +18,35 @@ # along with this program. If not, see . # ############################################################################## - import logging import time -import openerp -from openerp.osv import osv -from openerp.tools.translate import _ +from openerp.tools import DEFAULT_SERVER_DATE_FORMAT +from datetime import datetime, timedelta +from openerp import _, api, fields, models +from openerp.exceptions import Warning _logger = logging.getLogger(__name__) -class ir_sequence_type(openerp.osv.osv.osv): + +class ir_sequence_type(models.Model): _name = 'ir.sequence.type' _order = 'name' - _columns = { - 'name': openerp.osv.fields.char('Name', required=True), - 'code': openerp.osv.fields.char('Code', size=32, required=True), - } + + name = fields.Char(required=True) + code = fields.Char(size=32, required=True) _sql_constraints = [ ('code_unique', 'unique(code)', '`code` must be unique.'), ] -def _code_get(self, cr, uid, context=None): - cr.execute('select code, name from ir_sequence_type') - return cr.fetchall() -class ir_sequence(openerp.osv.osv.osv): +def _code_get(self): + self.env.cr.execute('select code, name from ir_sequence_type') + return self.env.cr.fetchall() + + +class ir_sequence(models.Model): """ Sequence model. The sequence model allows to define and use so-called sequence objects. @@ -54,172 +56,171 @@ class ir_sequence(openerp.osv.osv.osv): """ _name = 'ir.sequence' _order = 'name' - - def _get_number_next_actual(self, cr, user, ids, field_name, arg, context=None): + + def _get_number_next_actual(self): '''Return number from ir_sequence row when no_gap implementation, and number from postgres sequence when standard implementation.''' - res = dict.fromkeys(ids) - for element in self.browse(cr, user, ids, context=context): - if element.implementation != 'standard': - res[element.id] = element.number_next + res = {} + for element in self: + if element.implementation != 'standard': + element.number_next_actual = element.number_next else: - # get number from postgres sequence. Cannot use - # currval, because that might give an error when + # get number from postgres sequence. Cannot use currval, because that might give an error when # not having used nextval before. - statement = ( - "SELECT last_value, increment_by, is_called" - " FROM ir_sequence_%03d" - % element.id) - cr.execute(statement) - (last_value, increment_by, is_called) = cr.fetchone() + query = "SELECT last_value, increment_by, is_called FROM ir_sequence_%03d" % element.id + self.env.cr.execute(query) + (last_value, increment_by, is_called) = self.env.cr.fetchone() if is_called: - res[element.id] = last_value + increment_by + element.number_next_actual = last_value + increment_by else: - res[element.id] = last_value - return res + element.number_next_actual = last_value - def _set_number_next_actual(self, cr, uid, id, name, value, args=None, context=None): - return self.write(cr, uid, id, {'number_next': value or 0}, context=context) + def _set_number_next_actual(self): + for record in self: + record.write({'number_next': record.number_next_actual or 0}) - - _columns = { - 'name': openerp.osv.fields.char('Name', size=64, required=True), - 'code': openerp.osv.fields.selection(_code_get, 'Sequence Type', size=64), - 'implementation': openerp.osv.fields.selection( # TODO update the view - [('standard', 'Standard'), ('no_gap', 'No gap')], - 'Implementation', required=True, - help="Two sequence object implementations are offered: Standard " - "and 'No gap'. The later is slower than the former but forbids any" - " gap in the sequence (while they are possible in the former)."), - 'active': openerp.osv.fields.boolean('Active'), - 'prefix': openerp.osv.fields.char('Prefix', help="Prefix value of the record for the sequence"), - 'suffix': openerp.osv.fields.char('Suffix', help="Suffix value of the record for the sequence"), - 'number_next': openerp.osv.fields.integer('Next Number', required=True, help="Next number of this sequence"), - 'number_next_actual': openerp.osv.fields.function(_get_number_next_actual, fnct_inv=_set_number_next_actual, type='integer', required=True, string='Next Number', help='Next number that will be used. This number can be incremented frequently so the displayed value might already be obsolete'), - 'number_increment': openerp.osv.fields.integer('Increment Number', required=True, help="The next number of the sequence will be incremented by this number"), - 'padding' : openerp.osv.fields.integer('Number Padding', required=True, help="Odoo will automatically adds some '0' on the left of the 'Next Number' to get the required padding size."), - 'company_id': openerp.osv.fields.many2one('res.company', 'Company'), - } - _defaults = { - 'implementation': 'standard', - 'active': True, - 'company_id': lambda s,cr,uid,c: s.pool.get('res.company')._company_default_get(cr, uid, 'ir.sequence', context=c), - 'number_increment': 1, - 'number_next': 1, - 'number_next_actual': 1, - 'padding' : 0, - } + name = fields.Char(size=64, required=True) + code = fields.Selection(_code_get, 'Sequence Type', size=64) + implementation = fields.Selection( + [('standard', 'Standard'), ('no_gap', 'No gap')], + 'Implementation', required=True, default='standard', + help="Two sequence object implementations are offered: Standard " + "and 'No gap'. The later is slower than the former but forbids any" + " gap in the sequence (while they are possible in the former).") + active = fields.Boolean(default=True) + prefix = fields.Char(help="Prefix value of the record for the sequence") + suffix = fields.Char(help="Suffix value of the record for the sequence") + number_next = fields.Integer('Next Number', required=True, default=1, help="Next number of this sequence") + number_next_actual = fields.Integer(compute='_get_number_next_actual', inverse='_set_number_next_actual', + required=True, string='Next Number', default=1, + help="Next number that will be used. This number can be incremented " + "frequently so the displayed value might already be obsolete") + number_increment = fields.Integer('Increment Number', required=True, default=1, + help="The next number of the sequence will be incremented by this number") + padding = fields.Integer('Number Padding', required=True, default=0, + help="Odoo will automatically adds some '0' on the left of the " + "'Next Number' to get the required padding size.") + company_id = fields.Many2one('res.company', 'Company', + default=lambda s: s.env['res.company']._company_default_get('ir.sequence')) + use_date_range = fields.Boolean('Use subsequences per date_range') + date_range_ids = fields.One2many('ir.sequence.date_range', 'sequence_main_id', 'Subsequences') def init(self, cr): - return # Don't do the following index yet. - # CONSTRAINT/UNIQUE INDEX on (code, company_id) + return # Don't do the following index yet. + # CONSTRAINT/UNIQUE INDEX on (code, company_id) # /!\ The unique constraint 'unique_name_company_id' is not sufficient, because SQL92 # only support field names in constraint definitions, and we need a function here: # we need to special-case company_id to treat all NULL company_id as equal, otherwise # we would allow duplicate (code, NULL) ir_sequences. - cr.execute(""" + self.env.cr.execute(""" SELECT indexname FROM pg_indexes WHERE indexname = 'ir_sequence_unique_code_company_id_idx'""") - if not cr.fetchone(): - cr.execute(""" + if not self.env.cr.fetchone(): + self.env.cr.execute(""" CREATE UNIQUE INDEX ir_sequence_unique_code_company_id_idx ON ir_sequence (code, (COALESCE(company_id,-1)))""") - def _create_sequence(self, cr, id, number_increment, number_next): + def _create_sequence(self, number_increment, number_next, seq_date_id=False): """ Create a PostreSQL sequence. There is no access rights check. """ if number_increment == 0: - raise osv.except_osv(_('Warning!'),_("Increment number must not be zero.")) - assert isinstance(id, (int, long)) - sql = "CREATE SEQUENCE ir_sequence_%03d INCREMENT BY %%s START WITH %%s" % id - cr.execute(sql, (number_increment, number_next)) + raise Warning(_('Increment number must not be zero.')) + if seq_date_id: + sql = "CREATE SEQUENCE ir_sequence_%03d_%03d INCREMENT BY %%s START WITH %%s" % (self.id, seq_date_id.id) + else: + sql = "CREATE SEQUENCE ir_sequence_%03d INCREMENT BY %%s START WITH %%s" % self.id + self.env.cr.execute(sql, (number_increment, number_next)) - def _drop_sequence(self, cr, ids): + def _drop_sequence(self): """ Drop the PostreSQL sequence if it exists. There is no access rights check. """ - - ids = ids if isinstance(ids, (list, tuple)) else [ids] - assert all(isinstance(i, (int, long)) for i in ids), \ - "Only ids in (int, long) allowed." - names = ','.join('ir_sequence_%03d' % i for i in ids) + names = [] + for seq in self: + for seq_date_id in seq.date_range_ids: + names.append('ir_sequence_%03d_%03d' % (seq.id, seq_date_id)) + names.append('ir_sequence_%03d' % seq.id) + names = ','.join(names) # RESTRICT is the default; it prevents dropping the sequence if an # object depends on it. - cr.execute("DROP SEQUENCE IF EXISTS %s RESTRICT " % names) + self.env.cr.execute("DROP SEQUENCE IF EXISTS %s RESTRICT " % names) - def _alter_sequence(self, cr, id, number_increment, number_next=None): + def _alter_sequence(self, number_increment=None, number_next=None, seq_date_id=False): """ Alter a PostreSQL sequence. There is no access rights check. """ if number_increment == 0: - raise osv.except_osv(_('Warning!'),_("Increment number must not be zero.")) - assert isinstance(id, (int, long)) - seq_name = 'ir_sequence_%03d' % (id,) - cr.execute("SELECT relname FROM pg_class WHERE relkind = %s AND relname=%s", ('S', seq_name)) - if not cr.fetchone(): + raise Warning(_("Increment number must not be zero.")) + if seq_date_id: + seq_name = 'ir_sequence_%03d_%03d' % (self.id, seq_date_id.id) + else: + seq_name = 'ir_sequence_%03d' % (self.id) + self.env.cr.execute("SELECT relname FROM pg_class WHERE relkind = %s AND relname=%s", ('S', seq_name)) + if not self.env.cr.fetchone(): # sequence is not created yet, we're inside create() so ignore it, will be set later return - statement = "ALTER SEQUENCE %s INCREMENT BY %d" % (seq_name, number_increment) + statement = "ALTER SEQUENCE %s" % (seq_name, ) + if number_increment is not None: + statement += " INCREMENT BY %d" % (number_increment, ) if number_next is not None: statement += " RESTART WITH %d" % (number_next, ) - cr.execute(statement) + self.env.cr.execute(statement) - def create(self, cr, uid, values, context=None): + @api.model + def create(self, values): """ Create a sequence, in implementation == standard a fast gaps-allowed PostgreSQL sequence is used. """ - values = self._add_missing_default_values(cr, uid, values, context) - values['id'] = super(ir_sequence, self).create(cr, uid, values, context) + values = self._add_missing_default_values(values) + seq = super(ir_sequence, self).create(values) if values['implementation'] == 'standard': - self._create_sequence(cr, values['id'], values['number_increment'], values['number_next']) - return values['id'] + seq._create_sequence(values['number_increment'], values['number_next']) + return seq - def unlink(self, cr, uid, ids, context=None): - super(ir_sequence, self).unlink(cr, uid, ids, context) - self._drop_sequence(cr, ids) - return True + @api.multi + def unlink(self): + self._drop_sequence() + return super(ir_sequence, self).unlink() - def write(self, cr, uid, ids, values, context=None): - if not isinstance(ids, (list, tuple)): - ids = [ids] + @api.multi + def write(self, values): new_implementation = values.get('implementation') - rows = self.read(cr, uid, ids, ['implementation', 'number_increment', 'number_next'], context) - super(ir_sequence, self).write(cr, uid, ids, values, context) - for row in rows: + for seq in self: # 4 cases: we test the previous impl. against the new one. - i = values.get('number_increment', row['number_increment']) - n = values.get('number_next', row['number_next']) - if row['implementation'] == 'standard': + i = values.get('number_increment', seq.number_increment) + n = values.get('number_next', seq.number_next) + if seq.implementation == 'standard': if new_implementation in ('standard', None): # Implementation has NOT changed. # Only change sequence if really requested. - if row['number_next'] != n: - self._alter_sequence(cr, row['id'], i, n) - else: - # Just in case only increment changed - self._alter_sequence(cr, row['id'], i) + if seq.number_next != n: + seq._alter_sequence(number_next=n) + if seq.number_increment != i: + seq._alter_sequence(number_increment=i) + for seq_date_id in seq.date_range_ids: + seq._alter_sequence(number_increment=i, seq_date_id=seq_date_id) else: - self._drop_sequence(cr, row['id']) + seq._drop_sequence() else: if new_implementation in ('no_gap', None): pass else: - self._create_sequence(cr, row['id'], i, n) + seq._create_sequence(i, n) - return True + return super(ir_sequence, self).write(values) def _interpolate(self, s, d): if s: return s % d - return '' + return '' def _interpolation_dict(self): - t = time.localtime() # Actually, the server is always in UTC. + t = time.localtime() # Actually, the server is always in UTC. return { 'year': time.strftime('%Y', t), 'month': time.strftime('%m', t), @@ -234,40 +235,80 @@ class ir_sequence(openerp.osv.osv.osv): 'sec': time.strftime('%S', t), } - def _next(self, cr, uid, ids, context=None): - if not ids: - return False - if context is None: - context = {} - force_company = context.get('force_company') - if not force_company: - force_company = self.pool.get('res.users').browse(cr, uid, uid).company_id.id - sequences = self.read(cr, uid, ids, ['name','company_id','implementation','number_next','prefix','suffix','padding']) - preferred_sequences = [s for s in sequences if s['company_id'] and s['company_id'][0] == force_company ] - seq = preferred_sequences[0] if preferred_sequences else sequences[0] - if seq['implementation'] == 'standard': - cr.execute("SELECT nextval('ir_sequence_%03d')" % seq['id']) - seq['number_next'] = cr.fetchone() + def _next_do(self, seq_date_id=False): + cr = self.env.cr + if self.implementation == 'standard': + if seq_date_id: + sql = "SELECT nextval('ir_sequence_%03d_%03d')" % (self.id, seq_date_id.id) + else: + sql = "SELECT nextval('ir_sequence_%03d')" % self.id + cr.execute(sql) + number_next = cr.fetchone() else: - cr.execute("SELECT number_next FROM ir_sequence WHERE id=%s FOR UPDATE NOWAIT", (seq['id'],)) - cr.execute("UPDATE ir_sequence SET number_next=number_next+number_increment WHERE id=%s ", (seq['id'],)) - self.invalidate_cache(cr, uid, ['number_next'], [seq['id']], context=context) + if seq_date_id: + model_name = 'ir_sequence_date_range' + model_obj = self.env['ir.sequence.date_range'] + id = seq_date_id + else: + model_name = 'ir_sequence' + model_obj = self + id = self + number_next = id.number_next + cr.execute("SELECT number_next FROM %s WHERE id=%s FOR UPDATE NOWAIT" % (model_name, id.id)) + cr.execute("UPDATE %s SET number_next=number_next+%s WHERE id=%s " % (model_name, self.number_increment, id.id)) + model_obj.invalidate_cache(['number_next'], [id.id]) d = self._interpolation_dict() try: - interpolated_prefix = self._interpolate(seq['prefix'], d) - interpolated_suffix = self._interpolate(seq['suffix'], d) + interpolated_prefix = self._interpolate(self.prefix, d) + interpolated_suffix = self._interpolate(self.suffix, d) except ValueError: - raise osv.except_osv(_('Warning'), _('Invalid prefix or suffix for sequence \'%s\'') % (seq.get('name'))) - return interpolated_prefix + '%%0%sd' % seq['padding'] % seq['number_next'] + interpolated_suffix + raise Warning(_('Invalid prefix or suffix for sequence \'%s\'') % (self.get('name'))) + return interpolated_prefix + '%%0%sd' % self.padding % number_next + interpolated_suffix - def next_by_id(self, cr, uid, sequence_id, context=None): + def _create_date_range_seq(self, date): + year = datetime.strptime(date, DEFAULT_SERVER_DATE_FORMAT).strftime('%Y') + date_from = '{}-01-01'.format(year) + date_to = '{}-12-31'.format(year) + for line in self.date_range_ids: + if date < line.date_from < date_to: + date_to = datetime.strptime(line.date_from, '%Y-%m-%d') + timedelta(days=-1) + date_to = date_to.strftime('%Y-%m-%d') + elif date_from < line.date_to < date: + date_from = datetime.strptime(line.date_to, '%Y-%m-%d') + timedelta(days=1) + date_from = date_from.strftime('%Y-%m-%d') + seq_date_id = self.env['ir.sequence.date_range'].sudo().create({ + 'date_from': date_from, + 'date_to': date_to, + 'sequence_main_id': self.id, + }) + if self.implementation == 'standard': + self._create_sequence(self.number_increment, 1, seq_date_id=seq_date_id) + return seq_date_id + + def _next(self): + """ Returns the next number in the preferred sequence in all the ones given in self. + """ + if self.use_date_range: + dt = self.env.context.get('date', fields.Date.today()) + seq_date_id = False + for line in self.date_range_ids: + if line.date_from <= dt <= line.date_to: + seq_date_id = line + break + if not seq_date_id: + seq_date_id = self._create_date_range_seq(dt) + return self._next_do(seq_date_id=seq_date_id) + else: + return self._next_do() + + @api.multi + def next_by_id(self): """ Draw an interpolated string using the specified sequence.""" - self.check_access_rights(cr, uid, 'read') - company_ids = self.pool.get('res.company').search(cr, uid, [], context=context) + [False] - ids = self.search(cr, uid, ['&',('id','=', sequence_id),('company_id','in',company_ids)]) - return self._next(cr, uid, ids, context) + self.check_access_rights('read') + return self._next() - def next_by_code(self, cr, uid, sequence_code, context=None): + @api.model + def next_by_code(self, sequence_code): """ Draw an interpolated string using a sequence with the requested code. If several sequences with the correct code are available to the user (multi-company cases), the one from the user's current company will @@ -277,35 +318,86 @@ class ir_sequence(openerp.osv.osv.osv): ``force_company`` key with the ID of the company to use instead of the user's current company for the sequence selection. A matching sequence for that - specific company will get higher priority. + specific company will get higher priority. """ - self.check_access_rights(cr, uid, 'read') - company_ids = self.pool.get('res.company').search(cr, uid, [], context=context) + [False] - ids = self.search(cr, uid, ['&', ('code', '=', sequence_code), ('company_id', 'in', company_ids)]) - return self._next(cr, uid, ids, context) + self.check_access_rights('read') + company_ids = self.env['res.company'].search([]).ids + [False] + seq_ids = self.search(['&', ('code', '=', sequence_code), ('company_id', 'in', company_ids)]) + if not seq_ids: + return False + force_company = self.env.context.get('force_company') + if not force_company: + self.env.user.company_id + preferred_sequences = [s for s in seq_ids if s.company_id and s.company_id == force_company] + seq_id = preferred_sequences[0] if preferred_sequences else seq_ids[0] + return seq_id._next() - def get_id(self, cr, uid, sequence_code_or_id, code_or_id='id', context=None): + @api.model + def get_id(self, sequence_code_or_id, code_or_id='id'): """ Draw an interpolated string using the specified sequence. The sequence to use is specified by the ``sequence_code_or_id`` argument, which can be a code or an id (as controlled by the ``code_or_id`` argument. This method is deprecated. """ - # TODO: bump up to warning after 6.1 release - _logger.debug("ir_sequence.get() and ir_sequence.get_id() are deprecated. " - "Please use ir_sequence.next_by_code() or ir_sequence.next_by_id().") + _logger.warning("ir_sequence.get() and ir_sequence.get_id() are deprecated. " + "Please use ir_sequence.next_by_code() or ir_sequence.next_by_id().") if code_or_id == 'id': - return self.next_by_id(cr, uid, sequence_code_or_id, context) + return self.browse(sequence_code_or_id).next_by_id() else: - return self.next_by_code(cr, uid, sequence_code_or_id, context) + return self.next_by_code(sequence_code_or_id) - def get(self, cr, uid, code, context=None): + @api.model + def get(self, code): """ Draw an interpolated string using the specified sequence. The sequence to use is specified by its code. This method is deprecated. """ - return self.get_id(cr, uid, code, 'code', context) + return self.get_id(code, 'code') +class ir_sequence_date_range(models.Model): + _name = 'ir.sequence.date_range' + _rec_name = "sequence_main_id" + + def _get_number_next_actual(self): + '''Return number from ir_sequence row when no_gap implementation, + and number from postgres sequence when standard implementation.''' + for element in self: + if element.sequence_main_id.implementation != 'standard': + element.number_next_actual = element.number_next + else: + # get number from postgres sequence. Cannot use currval, because that might give an error when + # not having used nextval before. + query = "SELECT last_value, increment_by, is_called FROM ir_sequence_%03d_%03d" % (element.sequence_main_id, element.id) + self.env.cr.execute(query) + (last_value, increment_by, is_called) = self.env.cr.fetchone() + if is_called: + element.number_next_actual = last_value + increment_by + else: + element.number_next_actual = last_value + + def _set_number_next_actual(self): + for record in self: + record.write({'number_next': record.number_next_actual or 0}) + + date_from = fields.Date('From', required=True) + date_to = fields.Date('To', required=True) + sequence_main_id = fields.Many2one("ir.sequence", 'Main Sequence', required=True, ondelete='cascade') + number_next = fields.Integer('Next Number', required=True, default=1, help="Next number of this sequence") + number_next_actual = fields.Integer(compute='_get_number_next_actual', inverse='_set_number_next_actual', + required=True, string='Next Number', default=1, + help="Next number that will be used. This number can be incremented " + "frequently so the displayed value might already be obsolete") + + @api.multi + def write(self, values): + res = super(ir_sequence_date_range, self).write(values) + for seq_date_id in self: + if seq_date_id.sequence_main_id.implementation == 'standard': + if values.get('number_next'): + seq_date_id.sequence_main_id._alter_sequence(number_next=values.get('number_next'), seq_date_id=seq_date_id) + return res + # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/openerp/addons/base/ir/ir_sequence_view.xml b/openerp/addons/base/ir/ir_sequence_view.xml index bf6b99b7c4a..213ef30424f 100644 --- a/openerp/addons/base/ir/ir_sequence_view.xml +++ b/openerp/addons/base/ir/ir_sequence_view.xml @@ -20,9 +20,17 @@ - + + + + + + + + +