[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:
@@ -32,7 +32,6 @@ import account_financial_report
|
||||
import wizard
|
||||
import report
|
||||
import product
|
||||
import ir_sequence
|
||||
import company
|
||||
import res_currency
|
||||
import edi
|
||||
|
||||
@@ -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',
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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:
|
||||
@@ -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
|
||||
|
||||
|
@@ -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 = [
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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),
|
||||
|
||||
@@ -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'])
|
||||
|
||||
@@ -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
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
@@ -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],
|
||||
|
||||
@@ -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
|
||||
|
||||
|
@@ -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'
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
@@ -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
@@ -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'):
|
||||
|
||||
@@ -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):
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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
|
||||
|
||||
|
Reference in New Issue
Block a user