[IMP] base, ir_sequence: added use_date_range field on ir.sequence, that allows to have several sequences running for the same one depending on date ranges (similar to what was existing previously on accounting with FY, which is now deprecated) + port to new API

This commit is contained in:
qdp-odoo
2014-11-21 10:09:29 +01:00
parent fb31d3803f
commit b92c6b3101
30 changed files with 286 additions and 281 deletions
-1
View File
@@ -32,7 +32,6 @@ import account_financial_report
import wizard
import report
import product
import ir_sequence
import company
import res_currency
import edi
-1
View File
@@ -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',
+3 -2
View File
@@ -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,
-60
View File
@@ -1,60 +0,0 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# OpenERP, Open Source Management Solution
# Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>).
#
# 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 <http://www.gnu.org/licenses/>.
#
##############################################################################
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:
-27
View File
@@ -1,27 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<openerp>
<data>
<record id="sequence_inherit_form" model="ir.ui.view">
<field name="name">ir.sequence.form</field>
<field name="model">ir.sequence</field>
<field name="inherit_id" ref="base.sequence_view"/>
<field name="arch" type="xml">
<page position="after">
<page string="Fiscal Years">
<field name="fiscal_ids" nolabel="1" colspan="4">
<tree string="Fiscal Year Sequences" editable="bottom">
<field name="fiscalyear_id"/>
<field name="sequence_id" domain="[('code','=',parent.code)]"/>
</tree>
<form string="Fiscal Year Sequence">
<field name="fiscalyear_id"/>
<field name="sequence_id" domain="[('code','=',parent.code)]"/>
</form>
</field>
</page>
</page>
</field>
</record>
</data>
</openerp>
@@ -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
1 id name model_id:id group_id:id perm_read perm_write perm_create perm_unlink
62 access_account_fiscal_position_template account.fiscal.position.template model_account_fiscal_position_template account.group_account_manager 1 1 1 1
63 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
64 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
65 access_temp_range temp.range model_temp_range account.group_account_manager 1 0 0 0
66 access_report_aged_receivable report.aged.receivable model_report_aged_receivable account.group_account_manager 1 1 1 1
67 access_report_invoice_created report.invoice.created model_report_invoice_created account.group_account_manager 1 1 1 1
87 access_account_analytic_accountant account.analytic.account accountant analytic.model_account_analytic_account account.group_account_user 1 1 1 1
88 access_account_account_type_invoice account.account.type invoice model_account_account_type account.group_account_invoice 1 1 1 1
89 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
90 access_account_tax_sale_manager account.tax sale manager model_account_tax base.group_sale_salesman 1 0 0 0
91 access_account_journal_sale_manager account.journal sale manager model_account_journal base.group_sale_salesman 1 0 0 0
92 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
93 access_account_treasury_report_manager account.treasury.report.manager model_account_treasury_report account.group_account_manager 1 0 0 0
94 access_account_financial_report account.financial.report model_account_financial_report account.group_account_user 1 1 1 1
95 access_account_financial_report_invoice account.financial.report invoice model_account_financial_report account.group_account_invoice 1 0 0 0
+1 -1
View File
@@ -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',
@@ -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 = [
+3 -3
View File
@@ -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,
+1 -1
View File
@@ -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),
+1 -1
View File
@@ -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
@@ -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'])
+1 -1
View File
@@ -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'])
@@ -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
+1 -1
View File
@@ -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
-3
View File
@@ -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
1 id name model_id:id group_id:id perm_read perm_write perm_create perm_unlink
28 access_report_workcenter_load report.workcenter.load model_report_workcenter_load mrp.group_mrp_manager 1 1 1 1
29 access_report_mrp_inout report.mrp.inout model_report_mrp_inout mrp.group_mrp_manager 1 1 1 1
30 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
31 access_product_product_user product.product user product.model_product_product mrp.group_mrp_user 1 0 0 0
32 access_product_template_user product.template user product.model_product_template mrp.group_mrp_user 1 0 0 0
33 access_product_uom_user product.uom user product.model_product_uom mrp.group_mrp_user 1 0 0 0
41 access_product_puom_categ product.uom.categ product.model_product_uom_categ mrp.group_mrp_user 1 0 0 0
42 access_resource_resource resource.resource resource.model_resource_resource mrp.group_mrp_user 1 0 0 0
43 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
44 access_product_supplierinfo_manager product.supplierinfo user product.model_product_supplierinfo mrp.group_mrp_manager 1 0 0 0
45 access_mrp_production_manager mrp.production manager model_mrp_production mrp.group_mrp_manager 1 0 0 0
46 access_procurement_manager procurement.order model_procurement_order mrp.group_mrp_manager 1 0 0 0
47 access_workcenter_manager mrp.production.workcenter.line model_mrp_production_workcenter_line mrp.group_mrp_manager 1 0 0 0
48 access_stock_move_mrp_manager stock.move mrp_manager stock.model_stock_move mrp.group_mrp_manager 1 0 0 0
49 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
50 access_stock_production_lot_user stock.production.lot stock.model_stock_production_lot mrp.group_mrp_user 1 1 1 1
51 access_stock_warehouse_orderpoint_user stock.warehouse.orderpoint stock.model_stock_warehouse_orderpoint mrp.group_mrp_user 1 0 0 0
52 access_stock_picking_mrp_manager stock.picking mrp_manager stock.model_stock_picking mrp.group_mrp_manager 1 0 0 0
+1 -1
View File
@@ -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],
+3 -3
View File
@@ -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,
@@ -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
1 id name model_id:id group_id:id perm_read perm_write perm_create perm_unlink
47 access_account_invoice_manager account.invoice manager account.model_account_invoice group_pos_manager 1 1 1 1
48 access_product_product_supplierinfo_user product.supplierinfo user product.model_product_supplierinfo group_pos_user 1 0 0 0
49 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
50 access_stock_warehouse_manager stock.warehouse manager stock.model_stock_warehouse group_pos_manager 1 0 0 0
51 access_stock_location_manager stock.location manager stock.model_stock_location group_pos_manager 1 0 0 0
52 access_product_uom_manager product.uom manager product.model_product_uom group_pos_manager 1 1 1 1
+1 -1
View File
@@ -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'
}
+2 -2
View File
@@ -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,
@@ -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
1 id name model_id:id group_id:id perm_read perm_write perm_create perm_unlink
28 access_account_invoice_line_purchase_manager account_invoice.line purchase manager account.model_account_invoice_line group_purchase_manager 1 0 0 0
29 access_account_invoice_tax_purchase account_invoice.tax purchase account.model_account_invoice_tax group_purchase_user 1 1 1 1
30 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
31 access_res_partner_purchase_user res.partner purchase base.model_res_partner group_purchase_user 1 0 0 0
32 access_account_journal_period account.journal.period account.model_account_journal_period group_purchase_user 1 1 1 0
33 access_account_journal account.journal account.model_account_journal group_purchase_user 1 0 0 0
@@ -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,
}
+1 -1
View File
@@ -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'):
+4 -4
View File
@@ -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)
}
@@ -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,
}
@@ -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):
+245 -153
View File
@@ -18,33 +18,35 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
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:
+9 -1
View File
@@ -20,9 +20,17 @@
<field name="suffix"/>
<field name="padding"/>
<field name="number_increment"/>
<field name="number_next_actual"/>
<field name="number_next_actual" attrs="{'invisible': [('use_date_range', '=', True)]}"/>
<field name="implementation"/>
<field name="use_date_range"/>
</group>
<field name="date_range_ids" attrs="{'invisible': [('use_date_range', '=', False)]}">
<tree string="Sequences" editable="top">
<field name="date_from"/>
<field name="date_to"/>
<field name="number_next_actual"/>
</tree>
</field>
<group col="3" string="Legend (for prefix, suffix)">
<group>
<label colspan="2" string="Current Year with Century: %%(year)s"/>
@@ -31,6 +31,8 @@
"access_ir_rule_group_erp_manager","ir_rule group_erp_manager","model_ir_rule","group_erp_manager",1,1,1,1
"access_ir_sequence_group_user","ir_sequence group_user","model_ir_sequence","group_user",1,0,0,0
"access_ir_sequence_group_system","ir_sequence group_system","model_ir_sequence","group_system",1,1,1,1
"access_ir_sequence_date_range_group_user","ir_sequence_date_range group_user","model_ir_sequence_date_range","group_user",1,0,0,0
"access_ir_sequence_date_range_group_system","ir_sequence_date_range group_system","model_ir_sequence_date_range","group_system",1,1,1,1
"access_ir_sequence_type_group_user","ir_sequence_type group_user","model_ir_sequence_type",,1,0,0,0
"access_ir_sequence_type_group_system","ir_sequence_type group_system","model_ir_sequence_type","group_system",1,1,1,1
"access_ir_translation_all","ir_translation all","model_ir_translation",,1,1,1,1
1 id name model_id:id group_id:id perm_read perm_write perm_create perm_unlink
31 access_ir_rule_group_erp_manager ir_rule group_erp_manager model_ir_rule group_erp_manager 1 1 1 1
32 access_ir_sequence_group_user ir_sequence group_user model_ir_sequence group_user 1 0 0 0
33 access_ir_sequence_group_system ir_sequence group_system model_ir_sequence group_system 1 1 1 1
34 access_ir_sequence_date_range_group_user ir_sequence_date_range group_user model_ir_sequence_date_range group_user 1 0 0 0
35 access_ir_sequence_date_range_group_system ir_sequence_date_range group_system model_ir_sequence_date_range group_system 1 1 1 1
36 access_ir_sequence_type_group_user ir_sequence_type group_user model_ir_sequence_type 1 0 0 0
37 access_ir_sequence_type_group_system ir_sequence_type group_system model_ir_sequence_type group_system 1 1 1 1
38 access_ir_translation_all ir_translation all model_ir_translation 1 1 1 1