~asertigs/openobject-addons/7.0

« back to all changes in this revision

Viewing changes to ags_gtin_sequence/gtin_sequence.py

  • Committer: Pablo
  • Date: 2014-08-05 07:32:08 UTC
  • Revision ID: pablo@pablo-pc-20140805073208-gu4o47ua816gt83m
[ADD/FIX] Añadido el indicador de extensión a los SSCCs, ahora ya son de la longitud correcta (18)
[FIX] Arreglado bug surgido al no estar preparada la actualización de secuencias padre en el write para secuencias repetidas pero de distinto tipo (faltaba en el search de hijos el criterio del tipo)
[FIX] Ahora las secuencias GTIN sólo deben ser únicas dentro del tipo de secuencia (pallet o producto) que sean
[MOD] Ahora cambiar la categoría de producto nunca borra el ean13, ni aunque la categoría no tenga numeración
[FIX] Problema cuando no estaba inicializada la configuración de dígitos de extensión de sscc
[FIX] Bugs varios en ags_gtin_sequence

Show diffs side-by-side

added added

removed removed

Lines of Context:
22
22
from openerp.osv import osv, orm, fields
23
23
from openerp.tools.translate import _
24
24
import re
 
25
from openerp.tools import SUPERUSER_ID
25
26
 
26
27
class gtin_sequence(osv.Model):
27
28
    _description = 'GTIN Sequence'
28
29
    _name = 'gtin_sequence.gtin_sequence'
29
 
#     _table = 'ags_ean_sequence'
30
30
    _inherits = { 'ir.sequence': 'sequence_id' }
31
31
    
32
32
    def _find_parent(self, cr, uid, ids, prefix, seq_type, context=None):
40
40
            prefixes_ids.remove(ids[0])
41
41
        prefixes = self.read(cr, uid, prefixes_ids, 'prefix', context)
42
42
        for i in range(1,len(prefix)):
43
 
#             print "compruebo", prefix[:-i]
44
43
            parent_seq_recs = filter(lambda pref: pref['prefix'] == prefix[:-i], prefixes)
45
44
            if parent_seq_recs:
46
45
                return parent_seq_recs[0]['id']
50
49
        seq_type = vals.get('type', context['default_type'])
51
50
        prefix = str(vals['aecoc_prefix'])
52
51
        parent_seq_id = self._find_parent(cr, uid, [], prefix, seq_type, context)
53
 
#         if parent_seq_id:
54
 
#             parent_seq = self.browse(cr, uid, parent_seq_id, context=context)
55
 
#             if parent_seq.number_next != 0:
56
 
#                 raise osv.except_osv(_('Error!'),
57
 
#                         _('The specified prefix overlaps with an used sequence'))
58
52
        vals['parent_seq_id'] = parent_seq_id
59
 
        
60
53
        length = (seq_type == 'product' and 12) or (seq_type == 'pallet' and 16) or 0
61
54
        vals['padding'] = length - len(str(vals['aecoc_prefix']))
62
 
        ean_seq_id = super(gtin_sequence, self).create(cr, uid, vals, context=context)
 
55
        #Aunque demos permisos para crear sobre ags.gtin.sequence, si no se tienen sobre ir.sequence no deja
 
56
        ean_seq_id = super(gtin_sequence, self).create(cr, SUPERUSER_ID, vals, context=context)
63
57
 
64
58
        #Buscamos si existen secuencias hijo para actualizar su padre. Estas serán, de las que compartan prefijo,
65
59
        #las que no tengan padre o el padre sea el de la secuencia que estamos creando (la insertamos entre "abuelo" y "nieto")
89
83
            seq_type = vals.get('type', seq.type)
90
84
            new_parent_seq_id = self._find_parent(cr, uid, ids, str(vals['aecoc_prefix']), seq_type , context)
91
85
            new_parent_seq = self.browse(cr, uid, new_parent_seq_id, context=context)
92
 
#             if new_parent_seq.id:
93
 
#                 if new_parent_seq.number_next != 0:
94
 
#                     raise osv.except_osv(_('Error!'),
95
 
#                             _('The specified prefix overlaps with an used sequence'))
96
86
            vals['parent_seq_id'] = new_parent_seq_id 
97
87
            
98
88
            #Ponemos al "abuelo" como padre de los antiguos hijos. Si la secuencia pasa de 1234XXX a 12345XX 
101
91
            self.write(cr, uid, children_ids, { 'parent_seq_id': old_parent_seq.id }, context)
102
92
            #Buscamos si con el nuevo prefijo existen secuencias hijo para actualizar su padre. Estas serán las que se solapen
103
93
            #y o no tengan padre o el padre sea el que obtuvimos con el nuevo prefijo (la insertamos entre "abuelo" y "nieto")
104
 
            children_ids = self.search(cr, uid, ['|',('parent_seq_id','=',False),('parent_seq_id','=',new_parent_seq_id),('prefix','=like', str(vals['aecoc_prefix']) + '%'),('id','!=',ids[0])], context=context)
 
94
            children_ids = self.search(cr, uid, ['|',('parent_seq_id','=',False),('parent_seq_id','=',new_parent_seq_id),
 
95
                                                 ('prefix','=like', str(vals['aecoc_prefix']) + '%'),('id','!=',ids[0]),('type','=',seq_type)], context=context)
105
96
            self.write(cr, uid, children_ids, { 'parent_seq_id': ids[0] }, context)
106
97
  
107
98
            seq_type = self.browse(cr, uid, ids[0], context).type
108
99
            length = (seq_type == 'product' and 12) or (seq_type == 'pallet' and 16) or 0
109
100
            vals['padding'] = length - len(str(vals['aecoc_prefix']))
110
101
            
111
 
            res = super(gtin_sequence, self).write(cr, uid, ids, vals, context=context)
 
102
            res = super(gtin_sequence, self).write(cr, SUPERUSER_ID, ids, vals, context=context)
112
103
            
113
104
            #Con la estructura de punteros actualizada, actualizamos los available de las secuencias implicadas
114
105
            self._update_available(cr, uid, seq.id, context=context)
119
110
                
120
111
            return res
121
112
            
122
 
        return super(gtin_sequence, self).write(cr, uid, ids, vals, context=context)
 
113
        return super(gtin_sequence, self).write(cr, SUPERUSER_ID, ids, vals, context=context)
123
114
 
124
115
    def unlink(self, cr, uid, ids, context=None):
125
116
        to_recalc_available = set()
136
127
            self.write(cr, uid, children_ids, { 'parent_seq_id': ean_seq.parent_seq_id.id }, context)
137
128
            
138
129
        res = super(gtin_sequence, self).unlink(cr, uid, ids, context=context)
139
 
        self.pool.get('ir.sequence').unlink(cr, uid, to_delete, context)
 
130
        self.pool.get('ir.sequence').unlink(cr, SUPERUSER_ID, to_delete, context)
140
131
        
141
132
        #Puede que de entre los eliminados, unos fueran padres de otros
142
133
        to_recalc_available -= set(ids)
146
137
            
147
138
        return res
148
139
 
 
140
    def is_internal(self, cr, uid, gtin13, context=None):
 
141
        product_seq_ids = self.search(cr, uid, [('type','=','product')], context=context)
 
142
        best_match = 0
 
143
        internal = None
 
144
        for seq in self.browse(cr, uid, product_seq_ids, context):
 
145
            prefix = str(seq.aecoc_prefix)
 
146
            if gtin13.startswith(prefix):
 
147
                if len(prefix) > best_match:
 
148
                    best_match = len(prefix)
 
149
                    internal = seq.internal
 
150
        return internal
149
151
        
150
152
    def next_ean(self, cr, uid, seq_type, internal=False, context=None):
151
153
        #Devuelve un número usando la secuencia con mayor prioridad que no esté agotada
160
162
            length = (seq_type == 'product' and 12) or (seq_type == 'pallet' and 16) or 0
161
163
            lastnumber = int(ean_seq.prefix + '9'*(length-len(ean_seq.prefix)))
162
164
            number_next = ean_seq.number_next
163
 
            print len(ean_seq.prefix), ean_seq.padding
164
165
            candidate_number = ean_seq.prefix + str(number_next).zfill(ean_seq.padding)
165
166
            found = False
166
167
            while not found and int(candidate_number) <= lastnumber:
 
168
                blk_collision = False
167
169
                candidate_number = ean_seq.prefix + str(number_next).zfill(ean_seq.padding)
168
170
                for child_seq in ean_seq.children_seq_ids:
169
171
                    #El candidato colisiona con un bloque con una secuencia hija
170
172
                    if candidate_number.startswith(child_seq.prefix):
171
173
                        number_next += pow(10,child_seq.padding) - int(candidate_number[-child_seq.padding:])
 
174
                        blk_collision = True
172
175
                        break
173
 
                found = True
 
176
                if not blk_collision:
 
177
                    found = True
174
178
            if number_next != ean_seq.number_next:
175
179
                self.write(cr, uid, ean_seq.id, { 'number_next': number_next }, context)
176
180
            if not found:
196
200
        n_prods = pow(10, prod_code_len)
197
201
        remaining = n_prods - number_next
198
202
        
199
 
        print "SECUENCIA:", sequence.prefix
200
203
        #Descontamos los bloques pertenecientes a las secuencias hijo 
201
204
        #que estén por encima de number_next
202
205
        for overlapping_seq in sequence.children_seq_ids:
220
223
            raise orm.except_orm(_("Error!"), _("Prefixes must be numeric"))
221
224
        return self.write(cr, uid, ids, {'prefix': field_value}, context=context)
222
225
        
223
 
#     def _search_prefix(self, cr, uid, obj, name, args, domain=None, context=None):
224
 
#         TODO comprobar que funciona
225
 
#         assert False, "compruebame!!"
226
 
#         for arg in args:
227
 
#             if arg[0] == 'aecoc_prefix':
228
 
#                 arg[0] = 'prefix'
229
 
#         return args
230
226
 
231
227
    _columns = {
232
228
        'sequence_id': fields.many2one('ir.sequence', 'Sequence', required=True, ondelete="cascade", select=True),
237
233
        'aecoc_prefix': fields.function(_calc_prefix, fnct_inv=_write_prefix, type='integer', method=True,
238
234
                                        string='Prefix', size=10, required=True, help="Prefix of the sequence (company prefix + interfix)"),
239
235
        'internal': fields.boolean('Internal numbering'),
240
 
#         'available': fields.function(_calc_available, type='float',method=True,string="Available codes", digits=(15,0),
241
 
#                                      store={
242
 
#                                         #Ojo! sólo se dispara cuando el usuario cambia number_next, no cuando se obtiene un
243
 
#                                         #número al llamar al método _next (pesar de que avanza number_next)
244
 
#                                         'ags.ean.sequence': (lambda self, cr, uid, ids, c={}: ids, ['number_next'], 20),
245
 
#                                     }),
246
236
        'available': fields.float("Available codes", (15,0)),
247
237
        'priority': fields.integer('Priority'),
248
238
        'type': fields.selection([('product','Product'), ('pallet','Pallet')],'Type'),
269
259
    
270
260
    def _unique_prefix(self, cr, uid, ids, context=None):
271
261
        for seq in self.browse(cr, uid, ids, context):
272
 
            same_prefix_ids = self.search(cr, uid, [('prefix','=',seq.prefix),('id','!=',seq.id)], context=context)
 
262
            same_prefix_ids = self.search(cr, uid, [('prefix','=',seq.prefix),('type','=',seq.type),('id','!=',seq.id)], context=context)
273
263
            if same_prefix_ids:
274
264
                return False
275
265
        return True
276
 
    
 
266
     
277
267
    _constraints = [
278
268
        (_unique_prefix, 'This prefix is already in use.', ['prefix']),
279
269
    ]
 
270
 
 
271
 
 
272