+
+
+
+
+
+
+
+
+
+
+
+ =3 and qry.table_name!='':
+# data = warehouse.run(currency, qry)
+# flag = False
+# qry.count = qry.count +1
+# qry_obj.write(cr, uid, qry_id, {'count': qry.count})
+# else:
+# data = mdx.run(currency)
+# else:
+# data = mdx.run(currency)
+ print 'Running Done...'
+ print 'Formatting Output...'
+# if cubex.query_log and flag:
+ if cubex.query_log:
+ log = context.get('log')
+ if log:
+ connection = schema.database_id.connection_url
+# warehouse.log(cr,uid,cubex,request,data,connection,context)
+ mdx.log(cr,uid,cubex,request,context)
+ return cube.mdx_output(data)
+olap_schema()
+
+class olap_database_tables(osv.osv):
+ _name = "olap.database.tables"
+ _description = "Olap Database Tables"
+ _columns = {
+ 'table_db_name': fields.char('Table Name',size = 64,required = True,readonly = True),
+ 'name': fields.char('End-User Name',size = 64,required = True),
+ 'columns': fields.one2many('olap.database.columns','table_id','Columns'),
+ 'fact_database_id': fields.many2one('olap.fact.database','Database Id',required = True,ondelete = 'cascade',readonly = True),
+ 'active': fields.boolean('Active'),
+ 'hide': fields.boolean('Hidden'),
+ }
+ _defaults = {
+ 'active': lambda * args: True,
+ 'hide': lambda * args: False
+ }
+ def name_get(self,cr,uid,ids,context = {}):
+ result = []
+ for t in self.browse(cr,uid,ids,context):
+ if t.name <> t.table_db_name:
+ result.append((t.id,t.name + ' (' + t.table_db_name + ')'))
+ else:
+ result.append((t.id,t.name))
+ return result
+
+ def show_col_view(self,cr,uid,ids,context = {}):
+ ids_cols = self.pool.get('olap.database.columns').search(cr,uid,([('table_id','=',ids[0])]))
+ id = self.pool.get('ir.ui.view').search(cr,uid,([('name','=','olap.database.columns.tree')]),context = {})[0]
+ return {
+ 'domain': "[('id','in', [" + ','.join(map(str,ids_cols)) + "])]",
+ 'name': 'Database Columns',
+ 'view_type': 'form',
+ 'view_mode': 'tree',
+ 'res_model': 'olap.database.columns',
+ 'views': [(id,'tree'),(False,'form')],
+ 'type': 'ir.actions.act_window',
+ }
+
+ def hide_col(self,cr,uid,ids,context = {}):
+ # To hide all the related columns also
+ for id in ids:
+ self.write(cr,uid,id,{'hide':True})
+ return {}
+
+ def show_col(self,cr,uid,ids,context = {}):
+ # To show or unhide all the columns also
+ for id in ids:
+ self.write(cr,uid,id,{'hide':False})
+ return {}
+
+
+olap_database_tables()
+
+class olap_database_columns(osv.osv):
+ _name = "olap.database.columns"
+ _description = "Olap Database Columns"
+ datatypes = {
+ 'timestamp': 'TimeStamp without Time Zone',
+ 'timestampz': 'TimeStamp with Time Zone',
+ 'numeric': 'Numeric',
+ 'int': 'Integer',
+ 'float8': 'Double Precesion',
+ 'varchar': 'Character Varying',
+ 'bool': 'Boolean',
+ 'bytea':'Byte A',
+ 'int2':'Small Integer',
+ 'int4':'Integer',
+ 'int8':'Big Integer',
+ 'text':'Text',
+ 'date':'Date',
+ 'time': 'TimeStamp without Time Zone',
+ 'number':'NUMBER',
+ }
+ def _datatypes_get(self,*args,**argv):
+ return self.datatypes.items()
+ _columns = {
+ 'column_db_name': fields.char('Column DBName',size = 64,required = True,readonly = True),
+ 'name': fields.char('Column Name',size = 64,required = True),
+ 'table_id': fields.many2one('olap.database.tables','Table Id',required = True,ondelete = 'cascade',select = True,readonly = True),
+ 'primary_key': fields.boolean('Primary Key'),
+ 'type': fields.selection(_datatypes_get,'Type',size = 64,required = True,readonly = True),
+ 'related_to': fields.many2one('olap.database.tables','Related To',required = False,readonly = True),
+ 'active': fields.boolean('Active'),
+ 'hide': fields.boolean('Hidden'),
+ }
+ _defaults = {
+ 'hide': lambda * args: False,
+ 'active': lambda * args: True,
+ 'primary_key': lambda * args: False,
+ }
+ def name_get(self,cr,uid,ids,context = {}):
+ result = []
+ for t in self.browse(cr,uid,ids,context):
+ if t.name <> t.column_db_name:
+ result.append((t.id,t.table_id.table_db_name + ' (' + t.name + ')'))
+ else:
+ result.append((t.id,t.table_id.table_db_name + ' (' + t.name + ')'))
+ return result
+
+
+ def search(self,cr,uid,args,offset = 0,limit = None,order = None,
+ context = None,count = False):
+ if not context:
+ return super(olap_database_columns,self).search(cr,uid,args,offset,limit,
+ order,context = context,count = count)
+ col_pool = self.pool.get('olap.database.columns')
+ if context and context.has_key('fk') and context['fk']:
+ if context.has_key('dim_x') and context['dim_x']:
+ dim_obj = self.pool.get('olap.dimension').browse(cr,uid,int(context['dim_x']))
+ make_ids = []
+ make_ids.append(dim_obj.cube_id.table_id.column_link_id.table_id.id)
+
+ for lines in dim_obj.cube_id.table_id.line_ids:
+ make_ids.append(lines.field_id.related_to.id)
+ make_ids.append(lines.field_id.table_id.id)
+ args = [('table_id','in',make_ids),('related_to','<>',False),('hide','<>',True),('active','<>',False)]
+ return super(olap_database_columns,self).search(cr,uid,args,offset,limit,order,context = context,count = count)
+
+ if args and context and context.has_key('flag') and context['flag']:
+ ids = args[0][2][0][2]
+
+ if ids:
+ col_obj = col_pool.browse(cr,uid,ids)
+ make_ids = []
+ for lines in col_obj:
+ make_ids.append(lines.related_to.id)
+ link_id = col_pool.browse(cr,uid,int(context['link_col']))
+ make_ids.append(link_id.table_id.id)
+ args = ['|',('table_id','in',make_ids),('related_to','in',make_ids),('primary_key','<>',True),('hide','<>',True),('active','<>',False)]
+ ids = super(olap_database_columns,self).search(cr,uid,args,offset,limit,order,context = context,count = count)
+ return ids
+ elif context and context.has_key('master_dim') and context['master_dim']:
+ make_ids = []
+ col_obj = col_pool.browse(cr,uid,int(context['link_col']))
+ args = ['|',('table_id','=',col_obj.related_to.id),('related_to','=',col_obj.table_id.id),('hide','<>',True),('active','<>',False)]
+ return super(olap_database_columns,self).search(cr,uid,args,offset,limit,order,context = context,count = count)
+ else:
+ col = col_pool.browse(cr,uid,int(context['link_col']))
+ base_table = col.table_id
+ args = ['|',('table_id','=',base_table.id),('related_to','=',base_table.id),('hide','<>',True),('active','<>',False)]
+ return super(olap_database_columns,self).search(cr,uid,args,offset,limit,order,context = context,count = count)
+
+
+ if context and context.has_key('filter_cols_cube'):
+ cube_obj = self.pool.get('olap.cube').browse(cr,uid,int(context['filter_cols_cube']))
+ make_ids = []
+ make_ids.append(cube_obj.table_id.column_link_id.related_to.id)
+ for lines in cube_obj.table_id.line_ids:
+ make_ids.append(lines.table_id.id)
+ if make_ids:
+ make_ids.append(cube_obj.table_id.line_ids[len(cube_obj.table_id.line_ids) - 1].field_id.related_to.id)
+ args = [('table_id','in',make_ids),('related_to','=',False),('primary_key','<>',True),('type','not in',['date','timestamp','timestampz','time']),('hide','<>',True),('active','<>',False)]
+ ids = super(olap_database_columns,self).search(cr,uid,args,offset,limit,
+ order,context = context,count = count)
+ return ids
+
+ elif context and context.has_key('filter_cols_hier'):
+ hier_obj = self.pool.get('olap.hierarchy').browse(cr,uid,int(context['filter_cols_hier']))
+ make_ids = []
+ if hier_obj.table_id.line_ids:
+ for lines in hier_obj.table_id.line_ids:
+ make_ids.append(lines.field_id.related_to.id)
+
+ if make_ids:
+ make_ids.append(hier_obj.table_id.column_link_id.related_to.id)
+ make_ids.append(hier_obj.table_id.column_link_id.table_id.id)
+ args = [('table_id','in',make_ids),('hide','<>',True),('active','<>',False)]
+ ids = super(olap_database_columns,self).search(cr,uid,args,offset,limit,
+ order,context = context,count = count)
+ return ids
+ else:
+ args = [('table_id','=',hier_obj.table_id.column_link_id.related_to.id)]
+ ids = super(olap_database_columns,self).search(cr,uid,args,offset,limit,
+ order,context = context,count = count)
+ return ids
+ elif context and context.has_key('fk') and context['fk']:
+ args = [('primary_key','=',True),('hide','<>',True),('active','<>',False)]
+
+ else:
+ if context and context.has_key('master_dim') and context['master_dim']:
+ dim_obj = self.pool.get('olap.dimension').browse(cr,uid,int(context['master_dim']))
+ lines = dim_obj.cube_id.table_id.line_ids
+ table_ids = []
+ for line in lines:
+ table_ids.append(line.table_id.id)
+ args = [('table_id','in',table_ids),('related_to','<>',False),('hide','<>',True),('active','<>',False)]
+ elif context and context.has_key('master_schema') and context['master_schema']:
+ args = [('primary_key','=','True')]
+ return super(olap_database_columns,self).search(cr,uid,args,offset,limit,
+ order,context = context,count = count)
+
+
+ def hide_col(self,cr,uid,ids,context = {}):
+ for id in ids:
+ self.write(cr,uid,id,{'hide':True})
+ return {}
+
+ def show_col(self,cr,uid,ids,context = {}):
+ for id in ids:
+ self.write(cr,uid,id,{'hide':True})
+ return {}
+
+ def field_add(self,cr,uid,ids,context = {}):
+ col_data = self.pool.get('olap.database.columns').read(cr,uid,ids,[],context)[0]
+ ctx_list = []
+ if col_data['related_to']:
+ table_id = col_data['related_to'][0]
+ else:
+ table_id = col_data['table_id'][0]
+ if context['parent_id']:
+ parent_id = context['parent_id']
+ val = {
+ 'cube_table_id':parent_id,
+ 'table_id':table_id,
+ 'field_id':ids[0]
+ }
+ id = self.pool.get('olap.cube.table.line').create(cr,uid,val,context)
+ else:
+ parent_id = self.pool.get('olap.cube.table').create(cr,uid,{'name':col_data['table_id'][1]},context)
+ ctx_list = [('client','web'),('app','bi'),('id',parent_id)]
+ return ctx_list
+
+ def make_hierarchy(self,cr,uid,ids,context = {}):
+ col_data = self.pool.get('olap.database.columns').read(cr,uid,ids,[],context)[0]
+ ctx_list = []
+ if context and context.has_key('hier_parent_id')and context['hier_parent_id']:
+ hier_obj = self.pool.get('olap.hierarchy').browse(cr,uid,context['hier_parent_id'])
+ pk_table = hier_obj.table_id.name
+ elif context and context.has_key('hier_parent_table'):
+ cube_table_obj = self.pool.get('olap.cube.table').browse(cr,uid,context['hier_parent_table'])
+ pk_table = cube_table_obj.name
+ val = {
+ 'field_name':col_data['name'],
+ 'name':col_data['name'],
+ 'primary_key_table':pk_table
+ }
+ if context['hier_parent_id']:
+ id = self.pool.get('olap.hierarchy').write(cr,uid,context['hier_parent_id'],val,context)
+ else:
+ if context['parent_name']: val['name'] = context['parent_name']
+ if context['parent_dimension'] :val['dimension_id'] = context['parent_dimension']
+ if context['hier_parent_table'] : val['table_id'] = context['hier_parent_table']
+ if context['parent_field_name'] : val['field_name'] = context['parent_field_name']
+ if context['parent_level'] : val['level_ids'] = conext['parent_level']
+ if context['parent_member_all']: val['member_all'] = context['parent_member_all']
+ if context['parent_member_default'] : val['member_default'] = context['parent_member_default']
+ if context['parent_type']: val['type'] = context['parent_type']
+ val['primary_key_table'] = col_data['table_id'][1]
+ id = self.pool.get('olap.hierarchy').create(cr,uid,val,context)
+ ctx_list = [('client','web'),('app','bi'),('id',id)]
+ return ctx_list
+
+olap_database_columns()
+
+class olap_cube_table(osv.osv):
+ _name = "olap.cube.table"
+ _description = "Olap cube table"
+
+ def write(self,cr,uid,ids,vals,context = None):
+ if vals and vals.get('available_table_ids',0) and context and (context.has_key('master_dim') or context.has_key('d_id') or context.has_key('parent_schema_id')):
+ new_fields = vals['available_table_ids'][0][2]
+ final = []
+ for data in self.browse(cr,uid,ids):
+ orignal_lines = []
+ for line in data.line_ids:
+ orignal_lines.append(line.id)
+
+ orignal_fields = []
+ for line in data.line_ids:
+ orignal_fields.append(line.field_id.id)
+ if len(orignal_fields) < len(new_fields):
+ if new_fields[:len(orignal_fields)] == orignal_fields:
+ new_fields = new_fields[len(orignal_fields):]
+ cols_obj = self.pool.get('olap.database.columns').browse(cr,uid,new_fields)
+ val = {}
+ val['cube_table_id'] = ids[0]
+ for col in cols_obj:
+ val['table_id'] = col.table_id.id
+ val['field_id'] = col.id
+ id = self.pool.get('olap.cube.table.line').create(cr,uid,val,context = context)
+ else:
+ cols_obj = self.pool.get('olap.database.columns').unlink(cr,uid,orignal_lines)
+ cols_obj = self.pool.get('olap.database.columns').browse(cr,uid,new_fields)
+ val = {}
+ val['cube_table_id'] = ids[0]
+ for col in cols_obj:
+ val['table_id'] = col.table_id.id
+ val['field_id'] = col.id
+ id = self.pool.get('olap.cube.table.line').create(cr,uid,val,context = context)
+
+ elif len(orignal_fields) > len(new_fields):
+ if orignal_fields[:len(new_fields)] == new_fields:
+ remove_id = orignal_lines[len(new_fields):]
+ id = self.pool.get('olap.cube.table.line').unlink(cr,uid,remove_id,context = context)
+ else:
+ val = {}
+ id = self.pool.get('olap.cube.table.line').unlink(cr,uid,orignal_lines ,context = context)
+ cols_obj = self.pool.get('olap.database.columns').browse(cr,uid,new_fields)
+ val = {}
+ val['cube_table_id'] = ids[0]
+ for col in cols_obj:
+ val['table_id'] = col.table_id.id
+ val['field_id'] = col.id
+ id = self.pool.get('olap.cube.table.line').create(cr,uid,val,context = context)
+ return super(olap_cube_table,self).write(cr,uid,ids,vals,context)
+
+ def create(self,cr,uid,vals,context = None):
+ cube_table_id = super(olap_cube_table,self).create(cr,uid,vals,context)
+ if vals and vals.get('available_table_ids',0) and context and (context.has_key('d_id') or context.has_key('parent_schema_id') or context.has_key('master_dim') or context.has_key('d_id')):
+ lines_ids = vals['available_table_ids'][0][2]
+ cols_obj = self.pool.get('olap.database.columns').browse(cr,uid,lines_ids)
+ val = {}
+ val['cube_table_id'] = cube_table_id
+ for col in cols_obj:
+ val['table_id'] = col.table_id.id
+ val['field_id'] = col.id
+ id = self.pool.get('olap.cube.table.line').create(cr,uid,val,context = context)
+ return cube_table_id
+
+ def search(self,cr,uid,args,offset = 0,limit = None,order = None,
+ context = None,count = False):
+ if context and context.has_key('parent_schema_id'):
+ args = [('schema_id','=',context['parent_schema_id'])]
+ if context and context.has_key('d_id'):
+ dim_obj = self.pool.get('olap.dimension').browse(cr,uid,int(context['d_id']))
+ args = [('schema_id','=',dim_obj.cube_id.schema_id.id)]
+ return super(olap_cube_table,self).search(cr,uid,args,offset,limit,order,context = context,count = count)
+
+ def _available_table_get(self,cr,uid,ids,name,arg,context = None):
+ result = {}
+ parent_table_id = []
+ parent_table_ids = []
+ field_obj = self.pool.get('olap.database.columns')
+ for table in self.browse(cr,uid,ids,context):
+ if table.line_ids:
+ ids = []
+ ids = map(lambda x: x.field_id.id,table.line_ids)
+ result[table.id] = ids
+ else:
+ result[table.id] = []
+ return result
+
+ def _set_schema(self,cr,uid,context = {}):
+ if context and context.has_key('d_id'):
+ dim_obj = self.pool.get('olap.dimension').browse(cr,uid,int(context['d_id']))
+ return dim_obj.cube_id.schema_id.id
+ if context and context.has_key('parent_schema_id'):
+ return context['parent_schema_id']
+
+ def _set_name(self,cr,uid,context = {}):
+ if context and context.has_key('d_id'):
+ dim_obj = self.pool.get('olap.dimension').browse(cr,uid,int(context['d_id']))
+ return dim_obj.cubeAid.table_id.name
+
+ def _get_id(self,cr,uid,ids,context = {}):
+ if context and context.has_key('d_id'):
+ dim_obj = self.pool.get('olap.dimension').browse(cr,uid,int(context['d_id']))
+ table_id = self.pool.get('olap.database.tables').search(cr,uid,[('table_db_name','in',[dim_obj.cube_id.table_id.name]),('fact_database_id','=',dim_obj.cube_id.schema_id.database_id.id)])
+ col_ids = self.pool.get('olap.database.columns').search(cr,uid,[('table_id','in',table_id),('hide','<>',True),('related_to','<>',False)])
+ else:
+ col_ids = self.pool.get('olap.database.columns').search(cr,uid,[('primary_key','=',True),('hide','<>',True)])
+ return col_ids
+
+ def _def_set(self,cr,uid,context = {}):
+ return []
+
+ _columns = {
+ 'name': fields.char('Table name',size = 64,required = True),
+ 'line_ids': fields.one2many('olap.cube.table.line','cube_table_id','Database Tables',required = True),
+ 'schema_id':fields.many2one('olap.schema','Schema id',ondelete = 'cascade'),
+ 'column_link_id':fields.many2one('olap.database.columns','Relational Column' ,required = True),
+ 'available_table_ids': fields.function(
+ _available_table_get,
+ method = True,
+ relation = 'olap.database.columns',
+ string = 'Available Tables',
+ type = "many2many"
+ ),
+ }
+ _defaults = {
+ 'schema_id':_set_schema,
+ }
+ def field_add(self,cr,uid,ids,context = {}):
+ return {}
+olap_cube_table()
+
+class olap_cube_table_line(osv.osv):
+ _name = "olap.cube.table.line"
+ _description = "Olap cube table"
+ _rec_name = 'table_id'
+ _columns = {
+ 'cube_table_id': fields.many2one('olap.cube.table','Cube Table',required = True,ondelete = 'cascade'),
+ 'table_id': fields.many2one('olap.database.tables','Database Table',required = True,ondelete = 'cascade'),
+ 'field_id': fields.many2one('olap.database.columns','Link Field'),
+ }
+ # Set the Table when changing field_id
+ def onchange_field_id(self,*args,**argv):
+ pass
+olap_cube_table_line()
+
+class olap_cube(osv.osv):
+ _name = "olap.cube"
+ _description = "Olap cube"
+
+ def _set_schema(self,cr,uid,context = {}):
+ if context and context.has_key('schema_id'):
+ return context['schema_id']
+ return False
+
+ _columns = {
+ 'name': fields.char('Cube name',size = 64,required = True),
+ 'table_id': fields.many2one('olap.cube.table','Fact table',size = 64,required = True, help="Table(s) for cube."),
+ 'schema_id': fields.many2one('olap.schema','Schema',readonly = True),
+ 'dimension_ids': fields.one2many('olap.dimension','cube_id','Dimensions'),
+ 'measure_ids': fields.one2many('olap.measure','cube_id','Measures'),
+ 'query_log': fields.boolean('Query Logging', help = "Enabling this will log all the queries in the browser"),
+ 'query_ids': fields.one2many('olap.query.logs','cube_id','Queries'),
+ }
+ _defaults = {
+ 'schema_id':_set_schema
+ }
+olap_cube()
+
+class olap_query_logs(osv.osv):
+ _name = "olap.query.logs"
+ _description = "Olap query logs"
+ _columns = {
+ 'user_id' : fields.many2one('res.users','Tiny ERP User'),
+ 'query':fields.text('Query',required = True),
+ 'time':fields.datetime('Time',required = True),
+ 'result_size':fields.integer('Result Size',readonly = True),
+ 'cube_id': fields.many2one('olap.cube','Cube',required = True),
+ 'count': fields.integer('Count', readonly=True),
+ 'schema_id': fields.many2one('olap.schema','Schema',readonly = True),
+# 'table_name': fields.char('Table Name', size=164, readonly = True),
+ }
+
+ _defaults = {
+ 'count':lambda * args: 0
+ }
+olap_query_logs()
+
+
+class olap_dimension(osv.osv):
+ _name = "olap.dimension"
+ _description = "Olap dimension"
+
+ def _set_cube(self,cr,uid,context = {}):
+ if context and context.has_key('cube_id'):
+ return context['cube_id']
+ return False
+
+ _columns = {
+ 'name': fields.char('Dimension name',size = 64,required = True),
+ 'cube_id': fields.many2one('olap.cube','Cube',required = True),
+ 'hierarchy_ids': fields.one2many('olap.hierarchy','dimension_id','Hierarchies'),
+ }
+ _defaults = {
+ 'cube_id':_set_cube,
+ }
+
+olap_dimension()
+
+class olap_hierarchy(osv.osv):
+ _name = "olap.hierarchy"
+ _description = "Olap hierarchy"
+ _order = "sequence, id"
+ hierarchy_type = {
+ 'date': 'Date',
+ 'date_year': 'Year of Date',
+ 'date_quarter': 'Quarter of Date',
+ 'date_month': 'Month of Date',
+ 'many2one': 'Many2one'
+ }
+
+ def _set_dimension(self,cr,uid,context = {}):
+ if context and context.has_key('dimension_id'):
+ return context['dimension_id']
+ return False
+
+ def _set_name(self,cr,uid,context = {}):
+ if context and context.has_key('dimension_id'):
+ dim_obj = self.pool.get('olap.dimension').browse(cr,uid,int(context['dimension_id']))
+ return dim_obj.name
+ return False
+
+ def _hierarchy_get(self,*args,**argv):
+ return self.hierarchy_type.items()
+
+ _columns = {
+ 'name': fields.char('Hierarchy name',size = 64,required = True),
+ 'primary_key': fields.char('Primary key',size = 64),
+ 'primary_key_table': fields.char('Primary key table',size = 64),
+ 'sequence': fields.integer('Sequence',required = True),
+ 'dimension_id': fields.many2one('olap.dimension','Dimension',required = True),
+ 'level_ids': fields.one2many('olap.level','hierarchy_id','Levels'),
+ 'table_id': fields.many2one('olap.cube.table','Fact table(s)',required = True , help ="Table(s) to make hierarchy on the cube."),
+ }
+ _defaults = {
+ 'sequence': lambda * args: 1,
+ 'primary_key': lambda * args: 'id',
+ 'dimension_id':_set_dimension,
+ 'name':_set_name
+ }
+
+olap_hierarchy()
+
+class olap_level(osv.osv):
+ _name = "olap.level"
+ _description = "Olap level"
+ _order = "sequence, id"
+ _types = {
+ 'normal': levels.level_normal(),
+ 'date_year': levels.level_date_year(),
+ 'date_quarter': levels.level_date_quarter(),
+ 'date_month': levels.level_date_month()
+ }
+
+ def _set_hierarchy(self,cr,uid,context = {}):
+ if context and context.has_key('hierarchy_id'):
+ return context['hierarchy_id']
+ return False
+
+ def _set_name(self,cr,uid,context = {}):
+ if context and context.has_key('hierarchy_id'):
+ hier_obj = self.pool.get('olap.hierarchy').browse(cr,uid,int(context['hierarchy_id']))
+ return hier_obj.name
+
+ def onchange_column_name(self,cr,uid,ids,column,context = {}):
+ if not column:
+ return {}
+ val = {}
+ col = self.pool.get('olap.database.columns').browse(cr,uid,column)
+ val['table_name'] = col.table_id.table_db_name
+ val['column_id_name'] = col.column_db_name
+ if (col.type == 'date'):
+ val['type'] = 'date_year'
+ return {'value':val}
+
+ def _type_get(self,cr,uid,*args,**argv):
+ keys = self._types.keys()
+ return map(lambda x: (x,x),keys)
+
+
+ _columns = {
+ 'name': fields.char('Level name',size = 64,required = True),
+ 'column_name':fields.many2one('olap.database.columns','Columns Name',required = True),
+ 'column_id_name': fields.char('Column ID',size = 64,required = True),
+ 'type': fields.selection(selection = _type_get,string = 'Level class',size = 64,required = True),
+ 'table_name': fields.char('Table name',size = 64,required = True,help = "The name of the table on which the column is defined. If False, take the table from the hierarchy."),
+ 'sequence': fields.integer('Sequence',required = True),
+ 'hierarchy_id': fields.many2one('olap.hierarchy','Hierarchy',required = True),
+ }
+
+ _defaults = {
+ 'column_id_name': lambda * args: 'name',
+ 'sequence':lambda * args: '1',
+ 'type':lambda * args:'normal',
+ 'hierarchy_id':_set_hierarchy,
+ 'name':_set_name
+ }
+
+olap_level()
+
+
+class olap_measure(osv.osv):
+ _name = "olap.measure"
+ _description = "Olap measure"
+
+ def _set_cube(self,cr,uid,context = {}):
+ if context and context.has_key('cube_id'):
+ return context['cube_id']
+ return False
+
+ def onchange_measure_name(self,cr,uid,ids,column,context = {}):
+ val = {}
+ if not column:
+ return {}
+ col = self.pool.get('olap.database.columns').browse(cr,uid,column)
+ val['table_name'] = col.table_id.table_db_name
+ val['value_column_id_name'] = col.column_db_name
+ val['name'] = col.column_db_name
+ return {'value':val}
+
+ _columns = {
+ 'name': fields.char('Measure name',size = 64,required = True),
+ 'cube_id': fields.many2one('olap.cube','Cube',required = True),
+ 'value_column': fields.many2one('olap.database.columns','Fact Table Column'),
+ 'value_column_id_name': fields.char('Column ID',size = 64),
+ 'table_name': fields.char('Table name',size = 64,help = "The name of the table on which the column is defined. If False, take the table from the cube."),
+ 'measure_type':fields.selection([('fact_column','Fact Table Column'),('sql_expr','SQL Expression')],'Measure Type',required = True,help = "Select between auto column or sql expression for the measures"),
+ 'value_sql': fields.char('SQL Expression',size = 200,help = "You can provide valid sql expression. Make sure it have function with fully qualified column name like (sum,avg ...)(tablename.columnname (+,- ...) tablename.columnname)"),
+ 'agregator': fields.selection([('sum','Sum'),('count','count'),('avg','Average')],'Agregator',required = True),
+ 'datatype': fields.selection([('int','Integer'),('float','Float')],'Datatype',required = True),
+ 'formatstring': fields.selection([
+ ('none','None (0000.00)'),
+ ('cr_prefix','Prefix Default Currency (EUR 0000.00)'),
+ ('cr_postfix','Postfix Default Currency(0000.00 EUR)'),
+ ('cr_prefix_comma','Prefix Default Currency with comma seperator (EUR 0,000.00)'),
+ ('cr_postfix_comma','Postfix Default Currency with comma seperator (0,000.00 EUR)'),
+ ('comma_sep', 'Comma Seperator (0,000)')
+ ],
+ 'Format string',required = True, help=" Let you specify how the measure to be displayed in cube browser"),
+ }
+ _defaults = {
+ 'agregator': lambda * args: 'sum',
+ 'datatype': lambda * args: 'float',
+ 'formatstring': lambda * args: 'none',
+ 'cube_id':_set_cube,
+ 'measure_type':lambda * args:'fact_column',
+ }
+olap_measure()
+
+class olap_application(osv.osv):
+ _name = "olap.application"
+ _description = "Olap application"
+ _columns = {
+ 'name': fields.char('Application name',size = 64,required = True),
+ 'query':fields.text('Application Query'),
+ 'table_ids':fields.one2many('olap.application.table','application_id','Tables'),
+ 'field_ids': fields.one2many('olap.application.field','application_id','Fields'),
+ }
+olap_application()
+
+
+class olap_application_table(osv.osv):
+ _name = "olap.application.table"
+ _description = "Olap application table"
+ _columns = {
+ 'name': fields.char('Application table name',size = 64,required = True),
+ 'table_name': fields.char('Table name',size = 64,required = True),
+ 'is_hidden': fields.boolean('Hidden'),
+ 'application_id': fields.many2one('olap.application','Application Id',required = True),
+ }
+olap_application_table()
+
+class olap_application_field(osv.osv):
+ _name = "olap.application.field"
+ _description = "Olap application field"
+ _columns = {
+ 'name': fields.char('Application field name',size = 64,required = True),
+ 'table_name': fields.char('Application table name',size = 64),
+ 'field_name':fields.char('Field name',size = 64),
+ 'is_hidden': fields.boolean('Hidden'),
+ 'application_id': fields.many2one('olap.application','Application Id',required = True),
+ }
+olap_application_field()
+
+class olap_saved_query(osv.osv):
+ _name = "olap.saved.query"
+ _decription = "Olap Saved Query"
+# _rec_name = 'user_id'
+ _columns = {
+ 'name': fields.text('Query Name',size = 64),
+ 'user_id' : fields.many2one('res.users','User'),
+ 'query': fields.text('Query',required = True),
+ 'cube_id': fields.many2one('olap.cube','Cube',required = True),
+ 'mdx_id': fields.char('Module', size=64),
+ 'schema_id': fields.many2one('olap.schema','Schema',required = True),
+ 'time':fields.datetime('Time',required = True),
+ 'axis_keys': fields.text('Axis Keys'),
+ }
+olap_saved_query()
+# Wizard for the Load Data Structure
+# Replacement for the Load Wizard according to the new structure
+class bi_load_db_wizard(osv.osv_memory):
+ _name = 'bi.load.db.wizard'
+
+ def _get_fact_table(self,cr,uid,ctx):
+ if ctx and ctx.has_key('active_id'):
+ schema_obj = self.pool.get('olap.schema').browse(cr,uid,ctx['active_id'])
+ return schema_obj.name
+ return False
+
+ def _get_db_name(self,cr,uid,ctx):
+ if ctx and ctx.has_key('active_id'):
+ schema_obj = self.pool.get('olap.schema').browse(cr,uid,ctx['active_id'])
+ return schema_obj.database_id.name
+ return False
+
+ _columns = {
+ 'fact_table':fields.char('Fact Name' ,size = 64,readonly = True),
+ 'db_name':fields.char('Database Name',size = 64,readonly = True)
+ }
+
+ _defaults = {
+ 'fact_table':_get_fact_table,
+ 'db_name':_get_db_name,
+ }
+
+ def action_load(self,cr,uid,ids,context = None):
+ if context and context.has_key('active_id'):
+ lines = self.pool.get('olap.schema').browse(cr,uid,context['active_id'])
+ pool = pooler.get_pool(cr.dbname)
+# lines=pool.get('olap.schema').browse(cr, uid, part['id'],context)
+ id_db = lines.database_id.id
+ type = lines.database_id.type
+ db_name = lines.database_id.db_name
+ tobj = pool.get('olap.database.tables')
+ tcol = pool.get('olap.database.columns')
+ if type == 'postgres':
+# host = lines.database_id.db_host and "host=%s" % lines.database_id.db_host or ''
+# port = lines.database_id.db_port and "port=%s" % lines.database_id.db_port or ''
+# name = lines.database_id.db_name and "dbname=%s" % lines.database_id.db_name or ''
+# user = lines.database_id.db_login and "user=%s" % lines.database_id.db_login or ''
+# password = lines.database_id.db_password and "password=%s" % lines.database_id.db_password or ''
+# tdb = psycopg2.connect('%s %s %s %s %s' % (host, port, name, user, password))
+# cr_db = tdb.cursor()
+# cr.execute('select table_db_name,id from olap_database_tables where fact_database_id=%d', (id_db,))
+# tables = dict(cr.fetchall())
+# # Format for storing the tables
+# # tables['table_db_name']=id
+# tables_id = map(lambda x: str(tables[x]),tables)
+# cols={}
+# if tables_id:
+# cr.execute('select column_db_name,id,table_id from olap_database_columns where table_id in (' + ','.join(tables_id) +')')
+# else:
+# cr.execute('select column_db_name,id,table_id from olap_database_columns')
+#
+# for data in cr.fetchall():
+# cols[str(data[1])]=(data[0],int(data[2]))
+# # Format of storing the cols
+# # cols['id']=(col_db_name,table_id)
+# print 'Creating / Updating Tables...'
+# cr_db.execute("select table_name, table_catalog from INFORMATION_SCHEMA.tables as a where a.table_schema = 'public'")
+# for table in cr_db.fetchall():
+# val = {
+# 'fact_database_id':id_db,
+# 'table_db_name':table[0]
+# }
+#
+# if table[0] in tables.keys():
+# table_id=tobj.write(cr,uid,[tables[table[0]]], val, context)
+# else:
+# val['name']=table[0]
+# tables[val['name']] = tobj.create(cr,uid,val, context)
+# print 'Creating / Updating Columns...'
+# cr_db.execute("""SELECT
+# table_name, column_name, udt_name
+# from
+# INFORMATION_SCHEMA.columns
+# WHERE table_schema = 'public'""")
+#
+# for col in cr_db.fetchall():
+# val={
+# 'table_id': tables[col[0]],
+# 'column_db_name': col[1],
+# 'type': col[2],
+# }
+#
+# id_made=filter(lambda x:(int(cols[x][1])==int(tables[col[0]])),cols)
+# if col[1] in cols.keys() and col[0] in tables.keys()and id_made:
+# col_id=tcol.write(cr,uid,cols[tables[str(col[0])]], val, context)
+# else:
+# val['name']=col[1]
+# id_made = tcol.create(cr,uid,val, context)
+# cols[str(id_made)] = (val['name'],int(val['table_id']))
+# print 'Creating / Updating Constraints...'
+# cr_db.execute("""select
+# table_name,column_name
+# from
+# INFORMATION_schema.key_column_usage
+# where
+# constraint_name in (
+# select constraint_name from INFORMATION_SCHEMA .table_constraints
+# where
+# constraint_type = 'PRIMARY KEY')""")
+# print "Updating the Primary Key Constraint"
+# for constraint in cr_db.fetchall():
+# val={
+# 'primary_key':True
+# }
+#
+# id_to_write=filter(lambda x:(int(cols[x][1])==int(tables[constraint[0]])and(constraint[1]==cols[x][0])),cols)
+# col_id=tcol.write(cr,uid,int(id_to_write[0]),val,context)
+# print "Updating the Foreign key constraint"
+# cr_db.execute("""select
+# constraint_name,table_name
+# from
+# INFORMATION_schema.constraint_column_usage
+# where
+# constraint_name in (
+# select constraint_name from INFORMATION_SCHEMA.table_constraints
+# where
+# constraint_type = 'FOREIGN KEY')""")
+# for_key=dict(cr_db.fetchall())
+#
+# cr_db.execute("""select
+# table_name,column_name,constraint_name
+# from
+# INFORMATION_schema.key_column_usage
+# where
+# constraint_name in (
+# select constraint_name from INFORMATION_SCHEMA.table_constraints
+# where
+# constraint_type = 'FOREIGN KEY')""")
+
+# for constraint in cr_db.fetchall():
+# val={
+# 'related_to':tables[for_key[constraint[2]]]
+# }
+# id_to_write=filter(lambda x:(int(cols[x][1])==int(tables[constraint[0]])and (constraint[1]==cols[x][0])),cols)
+# col_id=tcol.write(cr,uid,int(id_to_write[0]),val,context)
+
+ host = lines.database_id.db_host and "host=%s" % lines.database_id.db_host or ''
+ port = lines.database_id.db_port and "port=%s" % lines.database_id.db_port or ''
+ name = lines.database_id.db_name and "dbname=%s" % lines.database_id.db_name or ''
+ user = lines.database_id.db_login and "user=%s" % lines.database_id.db_login or ''
+ password = lines.database_id.db_password and "password=%s" % lines.database_id.db_password or ''
+ tdb = psycopg2.connect('%s %s %s %s %s' % (host,port,name,user,password))
+ cr_db = tdb.cursor()
+ cr.execute('select table_db_name,id from olap_database_tables where fact_database_id=%d',(id_db,))
+ tables = dict(cr.fetchall())
+ # Format for storing the tables
+ # tables['table_db_name']=id
+ tables_id = map(lambda x: str(tables[x]),tables)
+ # Format of storing the cols
+ # cols['id']=(col_db_name,table_id)
+ print 'Creating / Updating Tables...'
+ cr_db.execute("select table_name, table_catalog from INFORMATION_SCHEMA.tables as a where a.table_schema = 'public'")
+ for table in cr_db.fetchall():
+ val = {
+ 'fact_database_id':id_db,
+ 'table_db_name':table[0]
+ }
+ if table[0] in tables.keys():
+ table_id = tobj.write(cr,uid,[tables[table[0]]],val,context)
+ else:
+ val['name'] = table[0]
+ tables[val['name']] = tobj.create(cr,uid,val,context)
+
+ print 'Creating / Updating Columns ....'
+ cols = {}
+ if tables_id:
+ cr.execute('select column_db_name,id,table_id from olap_database_columns where table_id in (' + ','.join(tables_id) + ')')
+ else:
+# cr.execute('select column_db_name,id,table_id from olap_database_columns ')
+ cr.execute("select olap_database_columns.column_db_name, olap_database_columns.id, olap_database_columns.table_id from olap_database_columns join olap_database_tables on olap_database_columns.table_id = olap_database_tables.id where olap_database_tables.fact_database_id=%d",(id_db,))
+ table_col = {}
+ cols_name = {}
+ for x in tables:
+ table_col[str(tables[x])] = [{}]
+ for data in cr.fetchall():
+ cols[str(data[1])] = (data[0],int(data[2]))
+ table_col[str(data[2])][0][data[0]] = data[1]
+ cols_name[str(data[0])] = (data[1],int(data[2]))
+ cr_db.execute("""SELECT
+ table_name, column_name, udt_name
+ from
+ INFORMATION_SCHEMA.columns
+ WHERE table_schema = 'public'""")
+ for col in cr_db.fetchall():
+ val = {
+ 'table_id': tables[col[0]],
+ 'column_db_name': col[1],
+ 'type': col[2],
+ }
+ id_made = filter(lambda x:(int(cols[x][1]) == int(tables[col[0]])),cols)
+ if col[0] in tables.keys() and col[1] in cols_name.keys() and id_made:
+ if table_col[str(tables[col[0]])][0] and col[1] in table_col[str(tables[col[0]])][0].keys():
+ col_id = tcol.write(cr,uid,table_col[str(tables[col[0]])][0][col[1]],val,context)
+ else:
+ val['name'] = col[1]
+ id_made = tcol.create(cr,uid,val,context)
+ cols[str(id_made)] = (val['name'],int(val['table_id']))
+ else:
+ val['name'] = col[1]
+ id_made = tcol.create(cr,uid,val,context)
+ cols[str(id_made)] = (val['name'],int(val['table_id']))
+
+ print 'Creating / Updating Constraints...'
+ cr_db.execute("""select
+ table_name,column_name
+ from
+ INFORMATION_schema.key_column_usage
+ where
+ constraint_name in (
+ select constraint_name from INFORMATION_SCHEMA .table_constraints
+ where
+ constraint_type = 'PRIMARY KEY')""")
+
+ print "Updating the Primary Key Constraint"
+ for constraint in cr_db.fetchall():
+ val = {
+ 'primary_key':True
+ }
+
+ id_to_write = filter(lambda x:(int(cols[x][1]) == int(tables[constraint[0]])and(constraint[1] == cols[x][0])),cols)
+ col_id = tcol.write(cr,uid,int(id_to_write[0]),val,context)
+
+ print "Updating the Foreign key constraint"
+ cr_db.execute("""select
+ constraint_name,table_name
+ from
+ INFORMATION_schema.constraint_column_usage
+ where
+ constraint_name in (
+ select constraint_name from INFORMATION_SCHEMA.table_constraints
+ where
+ constraint_type = 'FOREIGN KEY')""")
+ for_key = dict(cr_db.fetchall())
+
+ cr_db.execute("""select
+ table_name,column_name,constraint_name
+ from
+ INFORMATION_schema.key_column_usage
+ where
+ constraint_name in (
+ select constraint_name from INFORMATION_SCHEMA.table_constraints
+ where
+ constraint_type = 'FOREIGN KEY')""")
+
+ for constraint in cr_db.fetchall():
+ val = {
+ 'related_to':tables[for_key[constraint[2]]]
+ }
+ id_to_write = filter(lambda x:(int(cols[x][1]) == int(tables[constraint[0]])and (constraint[1] == cols[x][0])),cols)
+ if id_to_write:
+ col_id = tcol.write(cr,uid,int(id_to_write[0]),val,context)
+
+
+ elif type == 'mysql':
+ try:
+ import MySQLdb
+ host = lines.database_id.db_host or ''
+ port = lines.database_id.db_port or ''
+ db = lines.database_id.db_name or ''
+ user = lines.database_id.db_login or ''
+ passwd = lines.database_id.db_password or ''
+ tdb = MySQLdb.connect(host = host,port = port,db = db,user = user,passwd = passwd)
+
+ except Exception,e:
+ raise osv.except_osv('MySQLdb Packages Not Installed.',e)
+
+ cr_db = tdb.cursor()
+ cr.execute('select table_db_name,id from olap_database_tables where fact_database_id=%d',(id_db,))
+ tables = dict(cr.fetchall())
+ tables_id = map(lambda x: str(tables[x]),tables)
+ cols = {}
+ if tables_id:
+ cr.execute('select column_db_name,id,table_id from olap_database_columns where table_id in (' + ','.join(tables_id) + ')')
+ else:
+ cr.execute('select column_db_name,id,table_id from olap_database_columns')
+
+ for data in cr.fetchall():
+ cols[str(data[1])] = (data[0],int(data[2]))
+ cr_db.execute("select table_name, table_catalog from INFORMATION_SCHEMA.tables where table_schema =%s",(db_name))
+
+ for table in cr_db.fetchall():
+ val = {
+ 'fact_database_id':id_db,
+ 'table_db_name':table[0]
+ }
+
+ if table[0] in tables.keys():
+ table_id = tobj.write(cr,uid,[tables[table[0]]],val,context)
+
+ else:
+ val['name'] = table[0]
+ tables[val['name']] = tobj.create(cr,uid,val,context)
+ cr_db.execute("""SELECT
+ table_name, column_name, data_type
+ from
+ INFORMATION_SCHEMA.columns
+ WHERE table_schema = %s""",(db_name))
+
+ for col in cr_db.fetchall():
+
+ val = {
+ 'table_id': tables[col[0]],
+ 'column_db_name': col[1],
+ 'type': col[2],
+ }
+
+ id_made = filter(lambda x:(int(cols[x][1]) == int(tables[col[0]])),cols)
+ if col[1] in cols.keys() and col[0] in tables.keys()and id_made:
+ col_id = tcol.write(cr,uid,cols[tables[str(col[0])]],val,context)
+ else:
+ val['name'] = col[1]
+ id_made = tcol.create(cr,uid,val,context)
+ cols[str(id_made)] = (val['name'],int(val['table_id']))
+
+ cr_db.execute("""select
+ REFERENCED_COLUMN_NAME,REFERENCED_TABLE_NAME,COLUMN_NAME,TABLE_NAME
+ from
+ INFORMATION_schema.key_column_usage
+ where table_schema= %s and
+ constraint_name in (
+ select constraint_name from INFORMATION_SCHEMA .table_constraints
+ where
+ constraint_type in('PRIMARY KEY','FOREIGN KEY'))
+ """,(db_name))
+ # lines=pool.get('olap.schema').browse(cr, uid, part['id'],context)
+ for constraint in cr_db.fetchall():
+
+ if constraint[0]:
+ val = {
+ 'related_to':tables[constraint[1]]
+ }
+ else:
+
+ val = {
+ 'primary_key':True
+ }
+ id_to_write = filter(lambda x:(int(cols[x][1]) == int(tables[constraint[3]])and(constraint[2] == cols[x][0])),cols)
+ col_id = tcol.write(cr,uid,int(id_to_write[0]),val,context)
+
+ elif type == 'oracle':
+ try:
+ import cx_Oracle
+ host = lines.database_id.db_host or ''
+ port = lines.database_id.db_port or ''
+ db = lines.database_id.db_name or ''
+ user = lines.database_id.db_login.upper() or ''
+ passwd = lines.database_id.db_password or ''
+ tdb = cx_Oracle.connect(user,passwrd,host)
+
+ except Exception,e:
+ raise osv.except_osv('cx_Oracle Packages Not Installed.',e)
+
+ cr_db = tdb.cursor()
+ cr.execute('select table_db_name,id from olap_database_tables where fact_database_id=%d',(id_db,))
+ tables = dict(cr.fetchall())
+ tables_id = map(lambda x: str(tables[x]),tables)
+ cols = {}
+ if tables_id:
+ cr.execute('select column_db_name,id,table_id from olap_database_columns where table_id in (' + ','.join(tables_id) + ')')
+ else:
+ cr.execute('select column_db_name,id,table_id from olap_database_columns')
+
+ for data in cr.fetchall():
+ cols[str(data[1])] = (data[0],int(data[2]))
+
+ cr_db.execute("select table_name from all_tables where owner =%s",(user))
+ temp = cr_db.fetchall()
+ for table in temp:
+ val = {
+ 'fact_database_id':id_db,
+ 'table_db_name':table[0]
+ }
+
+ if table[0] in tables.keys():
+ table_id = tobj.write(cr,uid,[tables[table[0]]],val,context)
+
+ else:
+ val['name'] = table[0]
+ tables[val['name']] = tobj.create(cr,uid,val,context)
+
+ cr_db.execute("""SELECT
+ table_name, column_name, data_type
+ from
+ all_tab_columns
+ WHERE owner = %s""",(user))
+ temp = cr_db.fetchall()
+ for col in temp:
+ if col[2] == 'NUMBER':
+ type_col = 'numeric'
+ elif col[2] == 'DATE':
+ type_col = 'date'
+ elif col[2] == 'VARCHAR2':
+ type_col = 'varchar'
+ else:
+ type_col = col[2]
+ val = {
+ 'table_id': tables[col[0]],
+ 'column_db_name': col[1],
+ 'type': type_col,
+ }
+
+ id_made = filter(lambda x:(int(cols[x][1]) == int(tables[col[0]])),cols)
+ if col[1] in cols.keys() and col[0] in tables.keys()and id_made:
+ col_id = tcol.write(cr,uid,cols[tables[str(col[0])]],val,context)
+ else:
+ val['name'] = col[1]
+ id_made = tcol.create(cr,uid,val,context)
+ cols[str(id_made)] = (val['name'],int(val['table_id']))
+
+ cr_db.execute("""select
+ table_name,column_name,constraint_name
+ from
+ all_cons_columns
+ where
+ constraint_name in (
+ select constraint_name from all_constraints
+ where
+ constraint_type = 'P' and owner= %s)
+ """,(user))
+ temp = cr_db.fetchall()
+ pk_table = {}
+ for constraint in temp:
+ val = {
+ 'primary_key' : True
+ }
+ pk_table[constraint[2]] = constraint[0]
+
+ id_to_write = filter(lambda x : (int(cols[x][1]) == int(tables[constraint[0]])and(constraint[1] == cols[x][0])),cols)
+ col_id = tcol.write(cr,uid,int(id_to_write[0]),val,context)
+
+ cr_db.execute("""select
+ constraint_name,r_constraint_name from all_constraints
+ where
+ constraint_type = 'R' and owner = %s
+ """,(user))
+ constraints_map = {}
+ for data in cr_db.fetchall():
+ constraints_map[data[0]] = data[1]
+
+ cr_db.execute("""select
+ table_name,column_name,constraint_name
+ from
+ all_cons_columns
+ where
+ constraint_name in (
+ select constraint_name from all_constraints
+ where
+ constraint_type = 'R' and owner = %s)
+ """,(user))
+
+
+ temp = cr_db.fetchall()
+ for constraint in temp:
+ rel_constraint_name = constraints_map[constraint[2]]
+ req_table = pk_table[rel_constraint_name]
+ val = {
+ 'related_to' : tables[req_table]
+ }
+ id_to_write = filter(lambda x:(int(cols[x][1]) == int(tables[constraint[0]])and (constraint[1] == cols[x][0])),cols)
+ col_id = tcol.write(cr,uid,int(id_to_write[0]),val,context)
+
+ temp = pooler.get_pool(cr.dbname).get('olap.fact.database').write(cr,uid,[id_db],{'loaded':True})
+ wf_service = netsvc.LocalService('workflow')
+ wf_service.trg_validate(uid,'olap.schema',context['active_id'],'dbload',cr)
+ model_data_ids = self.pool.get('ir.model.data').search(cr,uid,[('model','=','ir.ui.view'),('name','=','view_olap_schema_form')])
+ resource_id = self.pool.get('ir.model.data').read(cr,uid,model_data_ids,fields = ['res_id'])[0]['res_id']
+
+ return {'type':'ir.actions.act_window_close' }
+# return{
+# 'domain': [],
+# 'name': 'view_olap_schema_form',
+# 'view_type': 'form',
+# 'view_mode': 'form,tree',
+# 'res_id': context['active_id'],
+# 'res_model': 'olap.schema',
+# 'view': [(resource_id,'form')],
+# 'type': 'ir.actions.act_window_close'
+# }
+#
+
+ def action_cancel(self,cr,uid,ids,context = None):
+
+ return {'type':'ir.actions.act_window_close' }
+
+bi_load_db_wizard()
+
+
+
+# Wizard for the Automatic Application Configuration
+# Replacement for the Load Wizard according to the new structure
+class bi_auto_configure_wizard(osv.osv_memory):
+ _name = 'bi.auto.configure.wizard'
+
+
+ def _get_name(self,cr,uid,ctx):
+ if ctx and ctx.has_key('active_id'):
+ schema_obj = self.pool.get('olap.schema').browse(cr,uid,ctx['active_id'])
+ return schema_obj.name
+ return False
+
+ _columns = {
+ 'name':fields.char('Fact Name' ,size = 64,readonly = True),
+
+ }
+
+ _defaults = {
+ 'name':_get_name,
+ }
+
+ def action_load(self,cr,uid,ids,context = None):
+ vals = {}
+ apptabnew_vals = {}
+ appfieldnew_vals = {}
+
+ ids = pooler.get_pool(cr.dbname).get('olap.schema').browse(cr,uid,context['active_id'])
+
+ if ids.app_detect == "Unknown Application":
+ raise wizard.except_wizard('Warning','The Application is Unknown, we can not configure it automatically.')
+
+ else:
+ app_objs = pooler.get_pool(cr.dbname).get('olap.application')
+ app_ids = app_objs.search(cr,uid,[])
+ app_res = app_objs.browse(cr,uid,app_ids)
+ app_id = ''
+ for x_app in app_res:
+ app_id = x_app['id']
+
+ apptab_objs = pooler.get_pool(cr.dbname).get('olap.application.table')
+ apptab_ids = apptab_objs.search(cr,uid,[])
+ apptab_res = apptab_objs.browse(cr,uid,apptab_ids)
+ apptab_name = []
+ map_apptab_name = {}
+ map_apptab_name_id = {}
+ for aptab in apptab_res:
+ apptab_name.append(aptab.name)
+ map_apptab_name_id[aptab.table_name] = aptab
+
+ appfield_objs = pooler.get_pool(cr.dbname).get('olap.application.field')
+ appfield_ids = appfield_objs.search(cr,uid,[])
+ appfield_res = appfield_objs.browse(cr,uid,appfield_ids)
+ appfield_data_res = appfield_objs.browse(cr,uid,appfield_ids)
+ appcol_name = []
+ for apcol in appfield_res:
+ appcol_name.append(apcol.name)
+
+ dbtab_obj = pooler.get_pool(cr.dbname).get('olap.database.tables')
+# id_tables=dbtab_obj.search(cr,uid,[('fact_database_id','=',ids.database_id.id),('table_db_name','not in',['inherit','res_roles','user_rule_group_rel','res_roles_users_rel','group_rule_group_rel'])])
+ id_tables = dbtab_obj.search(cr,uid,[('fact_database_id','=',ids.database_id.id)])
+ tables_main = dbtab_obj.read(cr,uid,id_tables,context = {'wizard':True})
+ for tables in tables_main:
+ end_user_name = {'name':(" ").join(map(lambda x:x.capitalize(),tables['table_db_name'].split("_")))}
+ table_new = dbtab_obj.write(cr,uid,tables['id'],end_user_name)
+ if not(tables['table_db_name'].startswith('ir') or tables['table_db_name'].startswith('wkf') or tables['table_db_name'].startswith('res_groups') or tables['table_db_name'].startswith('res_role')) and tables['table_db_name'] not in ['inherit','user_rule_group_rel','group_rule_group_rel']:
+ vals = {}
+
+ if len(apptab_ids) == 0 and (tables['table_db_name'] not in apptab_name):
+ vals['table_name'] = tables['table_db_name']
+ vals['name'] = (" ").join(map(lambda x:x.capitalize(),tables['name'].split("_")))
+ vals['is_hidden'] = tables['hide']
+ vals['application_id'] = app_id
+ table_new = dbtab_obj.write(cr,uid,tables['id'],{'hide':False})
+ apptab_new_obj = apptab_objs.create(cr,uid,vals)
+ else:
+ if map_apptab_name_id.has_key(tables['table_db_name']):
+ app_table = map_apptab_name_id[tables['table_db_name']]
+ if ((app_table['table_name'] == tables['table_db_name']) and not (app_table['table_name'] == tables['name'])):
+ vals['name'] = (" ").join(map(lambda x:x.capitalize(),tables['name'].split("_")))
+ vals['is_hidden'] = tables['hide']
+ tables_obj_new = apptab_objs.write(cr,uid,app_table['id'],vals)
+ else:
+ vals['table_name'] = tables['table_db_name']
+ vals['name'] = (" ").join(map(lambda x:x.capitalize(),tables['table_db_name'].split("_")))
+ vals['is_hidden'] = tables['hide']
+ vals['application_id'] = app_id
+ apptab_new_obj = apptab_objs.create(cr,uid,vals)
+ id_columns = pooler.get_pool(cr.dbname).get('olap.database.columns').search(cr,uid,[('table_id','in',id_tables)])
+ columns = pooler.get_pool(cr.dbname).get('olap.database.columns').read(cr,uid,id_columns,[])
+ for columns in columns:
+ vals = {}
+ if len(appfield_ids) == 0 and (columns['column_db_name'] not in appcol_name):
+ vals['field_name'] = columns['column_db_name']
+ vals['table_name'] = columns['table_id'][1]
+ vals['name'] = (" ").join(map(lambda x:x.capitalize(),columns['name'].split("_")))
+ vals['is_hidden'] = columns['hide']
+ vals['application_id'] = x_app['id']
+ appfield_new_obj = appfield_objs.create(cr,uid,vals)
+ else:
+ filter_column = filter(lambda x: columns['column_db_name'] == x['field_name'] and columns['table_id'][1] == x['table_name'],appfield_data_res)
+ if map_apptab_name_id.has_key(columns['table_id'][1]) and filter_column:
+ table_id_write = map_apptab_name_id[columns['table_id'][1]]
+ vals['name'] = (" ").join(map(lambda x:x.capitalize(),columns['name'].split("_")))
+ vals['is_hidden'] = columns['hide']
+ appfield_new_obj = appfield_objs.write(cr,uid,filter_column[0]['id'],vals)
+ else:
+ vals['field_name'] = columns['column_db_name']
+ vals['table_name'] = columns['table_id'][1]
+ vals['name'] = (" ").join(map(lambda x:x.capitalize(),columns['name'].split("_")))
+ vals['is_hidden'] = columns['hide']
+ vals['application_id'] = x_app['id']
+ appfield_new_obj = appfield_objs.create(cr,uid,vals)
+
+
+ database_tables = pooler.get_pool(cr.dbname).get('olap.database.tables')
+ id_tables = database_tables.search(cr,uid,[('fact_database_id','=',ids.database_id.id)])
+ tables = database_tables.read(cr,uid,id_tables,[])
+ make_id = []
+ for table in tables:
+ vals = {}
+ if (table['table_db_name'].startswith('ir') or table['table_db_name'].startswith('wkf')) or (table['table_db_name'].startswith('res_groups')) or (table['table_db_name'] in ['inherit','res_roles','user_rule_group_rel','res_roles_users_rel','group_rule_group_rel']):
+ vals['hide'] = True
+ vals['active'] = False
+ make_id.append(table['id'])
+ database_tables.write(cr,uid,table['id'],vals)
+
+ database_columns = pooler.get_pool(cr.dbname).get('olap.database.columns')
+ id_columns = database_columns.search(cr,uid,[('table_id','in',make_id)])
+ columns = database_columns.read(cr,uid,id_columns,[])
+ for col in columns:
+ val = {}
+ vals['hide'] = True
+ vals['active'] = False
+ database_columns.write(cr,uid,col['id'],vals)
+
+
+ wf_service = netsvc.LocalService('workflow')
+ wf_service.trg_validate(uid,'olap.schema',context['active_id'],'dbconfigure',cr)
+ model_data_ids = self.pool.get('ir.model.data').search(cr,uid,[('model','=','ir.ui.view'),('name','=','view_olap_schema_form')])
+ resource_id = self.pool.get('ir.model.data').read(cr,uid,model_data_ids,fields = ['res_id'])[0]['res_id']
+
+ return {'type':'ir.actions.act_window_close' }
+
+ def action_cancel(self,cr,uid,ids,context = None):
+
+ return {'type':'ir.actions.act_window_close' }
+
+bi_auto_configure_wizard()
+
+
+class olap_warehouse_wizard(osv.osv_memory):
+ _name = "olap.warehouse.wizard"
+ _description = "Olap Warehouse"
+
+ def _get_queries(self, cr, uid, context = {}):
+ query_obj = self.pool.get('olap.query.logs')
+ qry_ids = query_obj.search(cr, uid, [('user_id','=',uid),('count','>=',3)])
+ if qry_ids:
+ query = ''
+ for id in query_obj.browse(cr,uid,qry_ids,context):
+ if query == '':
+ query = id.query
+ else:
+ query = query + '\n'+id.query
+ return query
+ else:
+ return ''
+ def action_ok(self, cr, uid, ids, context = {}):
+ return {'type':'ir.actions.act_window_close' }
+
+ _columns = {
+ 'query': fields.text('Query', readonly=True),
+ }
+ _defaults = {
+ 'query': _get_queries,
+ }
+olap_warehouse_wizard()
+class olap_parameters_config_wizard(osv.osv_memory):
+ _name = "olap.parameters.config.wizard"
+ _description = "Olap Server Parameters"
+
+ def _get_host(self,cr,uid,context = None):
+ obj = self.pool.get('olap')
+ objid = self.pool.get('ir.model.data')
+ aid = objid._get_id(cr,uid,'olap','menu_url_cube_browser')
+ aid = objid.browse(cr,uid,aid,context = context).res_id
+ aid = self.pool.get('ir.actions.url').browse(cr,uid,aid,context = context)
+ s_p = Literal("http://").suppress() + Word(alphanums + "_" + ".") + Literal(":").suppress() + Word(nums) + Literal("/").suppress() + Word(alphanums + "_" + " ").suppress()
+ return s_p.parseString(aid.url)[0]
+
+ def _get_port(self,cr,uid,context = None):
+ obj = self.pool.get('olap')
+ objid = self.pool.get('ir.model.data')
+ aid = objid._get_id(cr,uid,'olap','menu_url_cube_browser')
+ aid = objid.browse(cr,uid,aid,context = context).res_id
+ aid = self.pool.get('ir.actions.url').browse(cr,uid,aid,context = context)
+ s_p = Literal("http://").suppress() + Word(alphanums + "_" + ".") + Literal(":").suppress() + Word(nums) + Literal("/").suppress() + Word(alphanums + "_" + " ").suppress()
+ return s_p.parseString(aid.url)[1]
+
+ _columns = {
+ 'host_name' : fields.char('Server Name',size = 64,help = "Put here the server address or IP \
+ Put localhost if its not clear.",required = True),
+ 'host_port' : fields.char('Port',size = 4,help = "Put the port for the server. Put 8080 if \
+ its not clear.",required = True),
+ }
+
+ _defaults = {
+ 'host_name': _get_host,
+ 'host_port': _get_port,
+ }
+
+ def action_cancel(self,cr,uid,ids,conect = None):
+ return {
+ 'view_type': 'form',
+ "view_mode": 'form',
+ 'res_model': 'ir.actions.configuration.wizard',
+ 'type': 'ir.actions.act_window',
+ 'target':'new',
+ }
+
+ def action_config(self,cr,uid,ids,context = None):
+ conf = self.browse(cr,uid,ids[0],context)
+ obj = self.pool.get('olap')
+ objid = self.pool.get('ir.model.data')
+ aid = objid._get_id(cr,uid,'olap','menu_url_cube_browser')
+ aid = objid.browse(cr,uid,aid,context = context).res_id
+ self.pool.get('ir.actions.url').write(cr,uid,[aid],{'url': 'http://' + (conf.host_name or 'localhost') + ':' + (conf.host_port or '8080') + '/browser'})
+
+ aid = objid._get_id(cr,uid,'olap','menu_url_cube_designer')
+ aid = objid.browse(cr,uid,aid,context = context).res_id
+ self.pool.get('ir.actions.url').write(cr,uid,[aid],{'url': 'http://' + (conf.host_name or 'localhost') + ':' + (conf.host_port or '8080') + '/designer'})
+
+ return {
+ 'view_type': 'form',
+ "view_mode": 'form',
+ 'res_model': 'ir.actions.configuration.wizard',
+ 'type': 'ir.actions.act_window',
+ 'target':'new',
+ }
+olap_parameters_config_wizard()
+
+# vim: ts=4 sts=4 sw=4 si et
diff --git a/addons/olap/wizard/__init__.py b/addons/olap/wizard/__init__.py
new file mode 100755
index 00000000000..a7b3a6af17f
--- /dev/null
+++ b/addons/olap/wizard/__init__.py
@@ -0,0 +1,34 @@
+##############################################################################
+#
+# Copyright (c) 2005-2006 TINY SPRL. (http://tiny.be) All Rights Reserved.
+#
+# WARNING: This program as such is intended to be used by professional
+# programmers who take the whole responsability of assessing all potential
+# consequences resulting from its eventual inadequacies and bugs
+# End users who are looking for a ready-to-use solution with commercial
+# garantees and support are strongly adviced to contract a Free Software
+# Service Company
+#
+# This program is Free Software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# 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 General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+##############################################################################
+
+import wizard_query_builder
+import wizard_load_data
+import wizard_load_configured_table
+import wizard_clear_logs
+import wizard_application_configure
+import wizard_load_columns
+import wizard_test_connection
diff --git a/addons/olap/wizard/wizard_application_configure.py b/addons/olap/wizard/wizard_application_configure.py
new file mode 100755
index 00000000000..3dfac9e2974
--- /dev/null
+++ b/addons/olap/wizard/wizard_application_configure.py
@@ -0,0 +1,194 @@
+##############################################################################
+#
+# Copyright (c) 2005-2006 TINY SPRL. (http://tiny.be) All Rights Reserved.
+#
+# WARNING: This program as such is intended to be used by professional
+# programmers who take the whole responsability of assessing all potential
+# consequences resulting from its eventual inadequacies and bugs
+# End users who are looking for a ready-to-use solution with commercial
+# garantees and support are strongly adviced to contract a Free Software
+# Service Company
+#
+# This program is Free Software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# 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 General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+##############################################################################
+import time
+
+import wizard
+import pooler
+from osv import osv
+import netsvc
+
+info = '''
+
+
+
'''
+
+form1 = '''
+
+
+
'''
+
+class wizard_application_configure(wizard.interface):
+
+ def configure_application(self,cr,uid,data,context):
+
+ vals={}
+ apptabnew_vals={}
+ appfieldnew_vals={}
+
+ ids=pooler.get_pool(cr.dbname).get('olap.schema').browse(cr,uid,data['id'])
+
+ if ids.app_detect == "Unknown Application":
+ raise wizard.except_wizard('Warning', 'The Application is Unknown, we can not configure it automatically.')
+
+ else:
+ app_objs = pooler.get_pool(cr.dbname).get('olap.application')
+ app_ids = app_objs.search(cr, uid, [])
+ app_res = app_objs.browse(cr,uid, app_ids)
+ app_id=''
+ for x_app in app_res:
+ app_id = x_app['id']
+
+ apptab_objs = pooler.get_pool(cr.dbname).get('olap.application.table')
+ apptab_ids = apptab_objs.search(cr, uid, [])
+ apptab_res = apptab_objs.browse(cr,uid, apptab_ids)
+ apptab_name=[]
+ for aptab in apptab_res:
+ apptab_name.append(aptab.name)
+
+ appfield_objs = pooler.get_pool(cr.dbname).get('olap.application.field')
+ appfield_ids = appfield_objs.search(cr, uid, [])
+ appfield_res = appfield_objs.browse(cr,uid, appfield_ids)
+ appcol_name=[]
+ for apcol in appfield_res:
+ appcol_name.append(apcol.name)
+
+
+ apptab_objs = pooler.get_pool(cr.dbname).get('olap.application.table')
+ apptab_ids = apptab_objs.search(cr, uid, [])
+ apptab_res = apptab_objs.browse(cr,uid, apptab_ids)
+# apptab_data_res = apptab_objs.read(cr,uid, apptab_ids,[])[0]
+
+ apptab_name=[]
+ map_apptab_name_id={}
+ for aptab in apptab_res:
+ apptab_name.append(aptab.name)
+ map_apptab_name_id[aptab.table_name]=aptab
+
+ appfield_objs = pooler.get_pool(cr.dbname).get('olap.application.field')
+ appfield_ids = appfield_objs.search(cr, uid, [])
+ appfield_res = appfield_objs.browse(cr,uid, appfield_ids)
+ appfield_data_res = appfield_objs.read(cr,uid, appfield_ids,[])
+
+ appcol_name=[]
+ for apcol in appfield_res:
+ appcol_name.append(apcol.name)
+
+ id_tables=pooler.get_pool(cr.dbname).get('olap.database.tables').search(cr,uid,[('fact_database_id','=',ids.database_id.id),('table_db_name','not in',['inherit','res_roles','user_rule_group_rel','res_roles_users_rel','group_rule_group_rel'])])
+ tables=pooler.get_pool(cr.dbname).get('olap.database.tables').read(cr,uid,id_tables,[])
+
+ for tables in tables:
+ if not(tables['table_db_name'].startswith('ir') or tables['table_db_name'].startswith('wkf') or tables['table_db_name'].startswith('res_groups')):
+ vals={}
+ if len(apptab_ids)==0 and (tables['table_db_name'] not in apptab_name):
+ vals['table_name']=tables['table_db_name']
+ vals['name']=(" ").join(map(lambda x:x.capitalize(),tables['name'].split("_")))
+ vals['is_hidden']=tables['hide']
+ vals['application_id']=app_id
+ apptab_new_obj=apptab_objs.create(cr,uid,vals)
+ else:
+ if map_apptab_name_id.has_key(tables['table_db_name']):
+ app_table = map_apptab_name_id[tables['table_db_name']]
+ if ((app_table['table_name']==tables['table_db_name']) and not (app_table['table_name']==tables['name'])):
+ vals['name']=aptable_obj.table_name
+ vals['hide']=aptable_obj.is_hidden
+ tables_obj_new=apptab_objs.write(cr,uid,tables['id'],vals)
+ else:
+ vals['table_name']=tables['table_db_name']
+ vals['name']=(" ").join(map(lambda x:x.capitalize(),tables['name'].split("_")))
+ vals['is_hidden']=tables['hide']
+ vals['application_id']=app_id
+ apptab_new_obj=apptab_objs.create(cr,uid,vals)
+
+ id_columns=pooler.get_pool(cr.dbname).get('olap.database.columns').search(cr,uid,[('table_id','in',id_tables)])
+ columns=pooler.get_pool(cr.dbname).get('olap.database.columns').read(cr,uid,id_columns,[])
+ for columns in columns:
+ vals={}
+ if len(appfield_ids) == 0 and (columns['column_db_name'] not in appcol_name):
+ vals['field_name']=columns['column_db_name']
+ vals['table_name']=columns['table_id'][1]
+ vals['name']=(" ").join(map(lambda x:x.capitalize(),columns['name'].split("_")))
+ vals['is_hidden']=columns['hide']
+ vals['application_id']=x_app['id']
+ appfield_new_obj=appfield_objs.create(cr,uid,vals)
+ else:
+ if map_apptab_name_id.has_key(columns['table_id'][1]):
+ table_id_write = map_apptab_name_id[columns['table_id'][1]]
+ filter_column=filter(lambda x: columns['column_db_name']==x['field_name'] and columns['table_id'][1]==x['table_name'],appfield_data_res)
+ vals['name']=(" ").join(map(lambda x:x.capitalize(),columns['name'].split("_")))
+ vals['is_hidden']=columns['hide']
+ appfield_new_obj=appfield_objs.write(cr,uid,filter_column[0]['id'],vals)
+ else:
+ vals['field_name']=columns['column_db_name']
+ vals['table_name']=columns['table_id'][1]
+ vals['name']=(" ").join(map(lambda x:x.capitalize(),columns['name'].split("_")))
+ vals['is_hidden']=columns['hide']
+ vals['application_id']=x_app['id']
+ appfield_new_obj=appfield_objs.create(cr,uid,vals)
+
+
+ database_tables = pooler.get_pool(cr.dbname).get('olap.database.tables')
+ id_tables=database_tables.search(cr,uid,[('fact_database_id','=',ids.database_id.id)])
+ tables=database_tables.read(cr,uid,id_tables,[])
+ make_id=[]
+ for table in tables:
+ vals={}
+ if (table['table_db_name'].startswith('ir') or table['table_db_name'].startswith('wkf')) or (table['table_db_name'].startswith('res_groups')) or (table['table_db_name'] in ['inherit','res_roles','user_rule_group_rel','res_roles_users_rel','group_rule_group_rel']):
+ vals['hide']=True
+ vals['active']=False
+ make_id.append(table['id'])
+ database_tables.write(cr,uid,table['id'],vals)
+
+ database_columns=pooler.get_pool(cr.dbname).get('olap.database.columns')
+ id_columns=database_columns.search(cr,uid,[('table_id','in',make_id)])
+ columns=database_columns.read(cr,uid,id_columns,[])
+ for col in columns:
+ val={}
+ vals['hide']=True
+ vals['active']=False
+ database_columns.write(cr,uid,col['id'],vals)
+
+
+ wf_service = netsvc.LocalService('workflow')
+ wf_service.trg_validate(uid, 'olap.schema', data['id'], 'dbconfigure', cr)
+ return {}
+
+
+ states = {
+ 'init': {
+ 'actions': [],
+ 'result': {'type': 'form', 'arch':form1, 'fields':{}, 'state':[('configure','Configure'),('end','Cancel')]}
+ },
+ 'configure': {
+ 'actions': [configure_application],
+ 'result': {'type':'form', 'arch':info, 'fields':{}, 'state':[('end','Ok')]}
+ },
+
+ }
+
+
+wizard_application_configure('olap.application.configuration')
+# vim: ts=4 sts=4 sw=4 si et
diff --git a/addons/olap/wizard/wizard_clear_logs.py b/addons/olap/wizard/wizard_clear_logs.py
new file mode 100755
index 00000000000..38b6531485a
--- /dev/null
+++ b/addons/olap/wizard/wizard_clear_logs.py
@@ -0,0 +1,83 @@
+##############################################################################
+#
+# Copyright (c) 2005-2006 TINY SPRL. (http://tiny.be) All Rights Reserved.
+#
+# WARNING: This program as such is intended to be used by professional
+# programmers who take the whole responsability of assessing all potential
+# consequences resulting from its eventual inadequacies and bugs
+# End users who are looking for a ready-to-use solution with commercial
+# garantees and support are strongly adviced to contract a Free Software
+# Service Company
+#
+# This program is Free Software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# 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 General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+##############################################################################
+import time
+
+import wizard
+import pooler
+from osv import osv
+
+
+info = '''
+
+
+
'''
+
+form1 = '''
+
+
+
'''
+
+field1 = {
+ # 'account_id': {'string':"Analytic Account", 'type':'many2one', 'relation':'account.analytic.account', 'required':True, 'domain':"[('type','=','normal')]"},
+ 'user_name': {'string':'User', 'type':'char','size':'64', 'required':True, 'readonly':True},
+# 'db_name': {'string':'Database Name', 'type':'char','size':'64', 'required':True, 'readonly':True},
+
+}
+
+def clear_logs(self,cr,uid,part,context={}):
+ ids=pooler.get_pool(cr.dbname).get('olap.query.logs').search(cr,uid,[('user_id','=',uid)])
+ pooler.get_pool(cr.dbname).get('olap.query.logs').unlink(cr, uid,ids,context)
+ return {}
+
+def _getdata(self,cr,uid,part,context={}):
+ ids=pooler.get_pool(cr.dbname).get('res.users').browse(cr,uid,uid)
+ part['form']['user_name']=ids['name']
+# part['form']['db_name']=lines.database_id.db_name
+ return part['form']
+
+class wizard_clear_logs(wizard.interface):
+
+ states = {
+
+ 'init': {
+ 'actions': [_getdata],
+ 'result': {'type':'form','arch':form1, 'fields':field1, 'state':[('end','Cancel'),('ok','Clear Logs')]}
+ },
+
+ 'ok': {
+ 'actions': [clear_logs],
+ 'result': {'type':'form','arch':info,'fields':{}, 'state':[('end','Ok')]}
+ },
+
+ 'info': {
+ 'actions': [],
+ 'result': {'type':'form', 'arch':info, 'fields':{}, 'state':[('end','Ok')]}
+ },
+
+ }
+
+wizard_clear_logs('olap.query.logs.clear')
diff --git a/addons/olap/wizard/wizard_load_columns.py b/addons/olap/wizard/wizard_load_columns.py
new file mode 100755
index 00000000000..f64a94399b4
--- /dev/null
+++ b/addons/olap/wizard/wizard_load_columns.py
@@ -0,0 +1,55 @@
+##############################################################################
+#
+# Copyright (c) 2005-2006 TINY SPRL. (http://tiny.be) All Rights Reserved.
+#
+# WARNING: This program as such is intended to be used by professional
+# programmers who take the whole responsability of assessing all potential
+# consequences resulting from its eventual inadequacies and bugs
+# End users who are looking for a ready-to-use solution with commercial
+# garantees and support are strongly adviced to contract a Free Software
+# Service Company
+#
+# This program is Free Software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# 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 General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+##############################################################################
+import time
+
+import wizard
+import pooler
+
+class wizard_load_columns(wizard.interface):
+ def _get_table_data(self, cr, uid, data, context={}):
+ pool_obj = pooler.get_pool(cr.dbname)
+ ids_cols=pool_obj.get('olap.database.columns').search(cr, uid, ([('table_id','=',data['id'])]),context={})
+ model_data_ids = pool_obj.get('ir.model.data').search(cr,uid,[('model','=','ir.ui.view'),('name','=','view_olap_database_columns_form')],context={})
+ resource_id = pool_obj.get('ir.model.data').read(cr,uid,model_data_ids,fields=['res_id'])[0]['res_id']
+ return {
+ 'domain': "[('id','in', ["+','.join(map(str,ids_cols))+"])]",
+ 'name': 'Database Columns',
+ 'view_type': 'form',
+ 'view_mode': 'tree,form',
+ 'res_model': 'olap.database.columns',
+ 'views': [(False,'tree'),(resource_id,'form')],
+ 'type': 'ir.actions.act_window',
+ }
+
+ states = {
+ 'init' : {
+ 'actions' : [],
+ 'result' : {'type' : 'action' ,'action':_get_table_data,'state':'end'}
+ }
+ }
+
+wizard_load_columns('olap.load.column')
diff --git a/addons/olap/wizard/wizard_load_configured_table.py b/addons/olap/wizard/wizard_load_configured_table.py
new file mode 100755
index 00000000000..da9a23cd1ba
--- /dev/null
+++ b/addons/olap/wizard/wizard_load_configured_table.py
@@ -0,0 +1,67 @@
+##############################################################################
+#
+# Copyright (c) 2005-2006 TINY SPRL. (http://tiny.be) All Rights Reserved.
+#
+# WARNING: This program as such is intended to be used by professional
+# programmers who take the whole responsability of assessing all potential
+# consequences resulting from its eventual inadequacies and bugs
+# End users who are looking for a ready-to-use solution with commercial
+# garantees and support are strongly adviced to contract a Free Software
+# Service Company
+#
+# This program is Free Software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# 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 General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+##############################################################################
+import time
+
+import wizard
+import pooler
+import netsvc
+
+class wizard_load_configured_table(wizard.interface):
+ def _get_table_data(self, cr, uid, data, context={}):
+ pool_obj = pooler.get_pool(cr.dbname)
+
+# vals={}
+# vals['configure']=True
+# vals['state']='dbconfigure'
+# pooler.get_pool(cr.dbname).get('olap.schema').write(cr,uid,data['id'],vals)
+
+ wf_service = netsvc.LocalService('workflow')
+ wf_service.trg_validate(uid, 'olap.schema', data['id'], 'dbconfigure', cr)
+
+ lines=pool_obj.get('olap.schema').read(cr, uid, data['id'],context={})
+ fact_ids=pool_obj.get('olap.database.tables').search(cr, uid, ([('fact_database_id','=',lines['database_id'][0])]),context={})
+ model_data_ids = pool_obj.get('ir.model.data').search(cr,uid,[('model','=','ir.ui.view'),('name','=','view_olap_database_tables_form')],context={})
+ resource_id = pool_obj.get('ir.model.data').read(cr,uid,model_data_ids,fields=['res_id'])[0]['res_id']
+
+ return {
+ 'domain': "[('id','in', ["+','.join(map(str,fact_ids))+"])]",
+ 'name': 'Database Tables',
+ 'view_type': 'form',
+ 'view_mode': 'tree,form',
+ 'res_model': 'olap.database.tables',
+ 'views': [(False,'tree'),(resource_id,'form')],
+ 'type': 'ir.actions.act_window'
+ }
+
+ states = {
+ 'init' : {
+ 'actions' : [],
+ 'result' : {'type' : 'action' ,'action':_get_table_data,'state':'end'}
+ }
+ }
+
+wizard_load_configured_table('olap.load.configuration.table')
diff --git a/addons/olap/wizard/wizard_load_data.py b/addons/olap/wizard/wizard_load_data.py
new file mode 100755
index 00000000000..320c69683ec
--- /dev/null
+++ b/addons/olap/wizard/wizard_load_data.py
@@ -0,0 +1,406 @@
+##############################################################################
+#
+# Copyright (c) 2005-2006 TINY SPRL. (http://tiny.be) All Rights Reserved.
+#
+# WARNING: This program as such is intended to be used by professional
+# programmers who take the whole responsability of assessing all potential
+# consequences resulting from its eventual inadequacies and bugs
+# End users who are looking for a ready-to-use solution with commercial
+# garantees and support are strongly adviced to contract a Free Software
+# Service Company
+#
+# This program is Free Software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# 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 General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+##############################################################################
+import psycopg2
+import time
+
+import wizard
+import pooler
+import netsvc
+
+info = '''
+
+
+
'''
+
+form1 = '''
+
+
+
+
+
+
+
+
+
+
'''
+
+field1 = {
+ 'fact_table': {'string':'Fact Name', 'type':'char','size':'64', 'required':True, 'readonly':True},
+ 'db_name': {'string':'Database Name', 'type':'char','size':'64', 'required':True, 'readonly':True},
+}
+
+def olap_db_connect(self,cr,uid,part,context={}):
+ pool = pooler.get_pool(cr.dbname)
+ lines=pool.get('olap.schema').browse(cr, uid, part['id'],context)
+ id_db=lines.database_id.id
+ type = lines.database_id.type
+ db_name = lines.database_id.db_name
+ tobj = pool.get('olap.database.tables')
+ tcol = pool.get('olap.database.columns')
+ if type == 'postgres':
+ host = lines.database_id.db_host and "host=%s" % lines.database_id.db_host or ''
+ port = lines.database_id.db_port and "port=%s" % lines.database_id.db_port or ''
+ name = lines.database_id.db_name and "dbname=%s" % lines.database_id.db_name or ''
+ user = lines.database_id.db_login and "user=%s" % lines.database_id.db_login or ''
+ password = lines.database_id.db_password and "password=%s" % lines.database_id.db_password or ''
+ tdb = psycopg2.connect('%s %s %s %s %s' % (host, port, name, user, password))
+ cr_db = tdb.cursor()
+ cr.execute('select table_db_name,id from olap_database_tables where fact_database_id=%d', (id_db,))
+ tables = dict(cr.fetchall())
+ tables_id = map(lambda x: str(tables[x]),tables)
+ cols={}
+ if tables_id:
+ cr.execute('select column_db_name,id,table_id from olap_database_columns where table_id in (' + ','.join(tables_id) +')')
+ else:
+ cr.execute('select column_db_name,id,table_id from olap_database_columns')
+
+ for data in cr.fetchall():
+ cols[str(data[1])]=(data[0],int(data[2]))
+
+ print 'Creating / Updating Tables...'
+ cr_db.execute("select table_name, table_catalog from INFORMATION_SCHEMA.tables as a where a.table_schema = 'public'")
+ for table in cr_db.fetchall():
+ val = {
+ 'fact_database_id':id_db,
+ 'table_db_name':table[0]
+ }
+
+ if table[0] in tables.keys():
+ table_id=tobj.write(cr,uid,[tables[table[0]]], val, context)
+ else:
+ val['name']=table[0]
+ tables[val['name']] = tobj.create(cr,uid,val, context)
+ print 'Creating / Updating Columns...'
+ cr_db.execute("""SELECT
+ table_name, column_name, udt_name
+ from
+ INFORMATION_SCHEMA.columns
+ WHERE table_schema = 'public'""")
+
+ for col in cr_db.fetchall():
+ val={
+ 'table_id': tables[col[0]],
+ 'column_db_name': col[1],
+ 'type': col[2],
+ }
+
+ id_made=filter(lambda x:(int(cols[x][1])==int(tables[col[0]])),cols)
+ if col[1] in cols.keys() and col[0] in tables.keys()and id_made:
+ col_id=tcol.write(cr,uid,cols[tables[str(col[0])]], val, context)
+ else:
+ val['name']=col[1]
+ id_made = tcol.create(cr,uid,val, context)
+ cols[str(id_made)] = (val['name'],int(val['table_id']))
+ print 'Creating / Updating Constraints...'
+ cr_db.execute("""select
+ table_name,column_name
+ from
+ INFORMATION_schema.key_column_usage
+ where
+ constraint_name in (
+ select constraint_name from INFORMATION_SCHEMA .table_constraints
+ where
+ constraint_type = 'PRIMARY KEY')""")
+ print "Updating the Primary Key Constraint"
+ for constraint in cr_db.fetchall():
+ val={
+ 'primary_key':True
+ }
+
+ id_to_write=filter(lambda x:(int(cols[x][1])==int(tables[constraint[0]])and(constraint[1]==cols[x][0])),cols)
+ col_id=tcol.write(cr,uid,int(id_to_write[0]),val,context)
+ print "Updating the Foreign key constraint"
+ cr_db.execute("""select
+ constraint_name,table_name
+ from
+ INFORMATION_schema.constraint_column_usage
+ where
+ constraint_name in (
+ select constraint_name from INFORMATION_SCHEMA.table_constraints
+ where
+ constraint_type = 'FOREIGN KEY')""")
+ for_key=dict(cr_db.fetchall())
+
+ cr_db.execute("""select
+ table_name,column_name,constraint_name
+ from
+ INFORMATION_schema.key_column_usage
+ where
+ constraint_name in (
+ select constraint_name from INFORMATION_SCHEMA.table_constraints
+ where
+ constraint_type = 'FOREIGN KEY')""")
+
+ for constraint in cr_db.fetchall():
+ val={
+ 'related_to':tables[for_key[constraint[2]]]
+ }
+ id_to_write=filter(lambda x:(int(cols[x][1])==int(tables[constraint[0]])and (constraint[1]==cols[x][0])),cols)
+ col_id=tcol.write(cr,uid,int(id_to_write[0]),val,context)
+
+
+ elif type =='mysql':
+ try:
+ import MySQLdb
+ host = lines.database_id.db_host or ''
+ port = lines.database_id.db_port or ''
+ db = lines.database_id.db_name or ''
+ user = lines.database_id.db_login or ''
+ passwd = lines.database_id.db_password or ''
+ tdb = MySQLdb.connect(host = host,port = port, db = db, user = user, passwd = passwd)
+
+ except Exception, e:
+ raise osv.except_osv('MySQLdb Packages Not Installed.',e )
+
+ cr_db = tdb.cursor()
+ cr.execute('select table_db_name,id from olap_database_tables where fact_database_id=%d', (id_db,))
+ tables = dict(cr.fetchall())
+ tables_id = map(lambda x: str(tables[x]),tables)
+ cols={}
+ if tables_id:
+ cr.execute('select column_db_name,id,table_id from olap_database_columns where table_id in (' + ','.join(tables_id) +')')
+ else:
+ cr.execute('select column_db_name,id,table_id from olap_database_columns')
+
+ for data in cr.fetchall():
+ cols[str(data[1])]=(data[0],int(data[2]))
+ cr_db.execute("select table_name, table_catalog from INFORMATION_SCHEMA.tables where table_schema =%s",(db_name))
+
+ for table in cr_db.fetchall():
+ val = {
+ 'fact_database_id':id_db,
+ 'table_db_name':table[0]
+ }
+
+ if table[0] in tables.keys():
+ table_id=tobj.write(cr,uid,[tables[table[0]]], val, context)
+
+ else:
+ val['name']=table[0]
+ tables[val['name']] = tobj.create(cr,uid,val, context)
+ cr_db.execute("""SELECT
+ table_name, column_name, data_type
+ from
+ INFORMATION_SCHEMA.columns
+ WHERE table_schema = %s""",(db_name))
+
+ for col in cr_db.fetchall():
+
+ val={
+ 'table_id': tables[col[0]],
+ 'column_db_name': col[1],
+ 'type': col[2],
+ }
+
+ id_made=filter(lambda x:(int(cols[x][1])==int(tables[col[0]])),cols)
+ if col[1] in cols.keys() and col[0] in tables.keys()and id_made:
+ col_id=tcol.write(cr,uid,cols[tables[str(col[0])]], val, context)
+ else:
+ val['name']=col[1]
+ id_made = tcol.create(cr,uid,val, context)
+ cols[str(id_made)] = (val['name'],int(val['table_id']))
+
+ cr_db.execute("""select
+ REFERENCED_COLUMN_NAME,REFERENCED_TABLE_NAME,COLUMN_NAME,TABLE_NAME
+ from
+ INFORMATION_schema.key_column_usage
+ where table_schema= %s and
+ constraint_name in (
+ select constraint_name from INFORMATION_SCHEMA .table_constraints
+ where
+ constraint_type in('PRIMARY KEY','FOREIGN KEY'))
+ """,(db_name))
+
+ for constraint in cr_db.fetchall():
+
+ if constraint[0]:
+ val={
+ 'related_to':tables[constraint[1]]
+ }
+ else:
+
+ val={
+ 'primary_key':True
+ }
+ id_to_write=filter(lambda x:(int(cols[x][1])==int(tables[constraint[3]])and(constraint[2]==cols[x][0])),cols)
+ col_id=tcol.write(cr,uid,int(id_to_write[0]),val,context)
+
+ elif type == 'oracle':
+ try:
+ import cx_Oracle
+ host = lines.database_id.db_host or ''
+ port = lines.database_id.db_port or ''
+ db = lines.database_id.db_name or ''
+ user = lines.database_id.db_login.upper() or ''
+ passwd = lines.database_id.db_password or ''
+ tdb = cx_Oracle.connect(user, passwrd, host)
+
+ except Exception, e:
+ raise osv.except_osv('cx_Oracle Packages Not Installed.',e )
+
+ cr_db = tdb.cursor()
+ cr.execute('select table_db_name,id from olap_database_tables where fact_database_id=%d', (id_db,))
+ tables = dict(cr.fetchall())
+ tables_id = map(lambda x: str(tables[x]),tables)
+ cols={}
+ if tables_id:
+ cr.execute('select column_db_name,id,table_id from olap_database_columns where table_id in (' + ','.join(tables_id) +')')
+ else:
+ cr.execute('select column_db_name,id,table_id from olap_database_columns')
+
+ for data in cr.fetchall():
+ cols[str(data[1])]=(data[0],int(data[2]))
+
+ cr_db.execute("select table_name from all_tables where owner =%s",(user))
+ temp = cr_db.fetchall()
+ for table in temp:
+ val = {
+ 'fact_database_id':id_db,
+ 'table_db_name':table[0]
+ }
+
+ if table[0] in tables.keys():
+ table_id=tobj.write(cr,uid,[tables[table[0]]], val, context)
+
+ else:
+ val['name']=table[0]
+ tables[val['name']] = tobj.create(cr,uid,val, context)
+
+ cr_db.execute("""SELECT
+ table_name, column_name, data_type
+ from
+ all_tab_columns
+ WHERE owner = %s""",(user))
+ temp = cr_db.fetchall()
+ for col in temp:
+ if col[2]=='NUMBER':
+ type_col='numeric'
+ elif col[2]=='DATE':
+ type_col='date'
+ elif col[2]=='VARCHAR2':
+ type_col='varchar'
+ else:
+ type_col=col[2]
+ val={
+ 'table_id': tables[col[0]],
+ 'column_db_name': col[1],
+ 'type': type_col,
+ }
+
+ id_made=filter(lambda x:(int(cols[x][1])==int(tables[col[0]])),cols)
+ if col[1] in cols.keys() and col[0] in tables.keys()and id_made:
+ col_id=tcol.write(cr,uid,cols[tables[str(col[0])]], val, context)
+ else:
+ val['name']=col[1]
+ id_made = tcol.create(cr,uid,val, context)
+ cols[str(id_made)] = (val['name'],int(val['table_id']))
+
+ cr_db.execute("""select
+ table_name,column_name,constraint_name
+ from
+ all_cons_columns
+ where
+ constraint_name in (
+ select constraint_name from all_constraints
+ where
+ constraint_type = 'P' and owner= %s)
+ """,(user))
+ temp = cr_db.fetchall()
+ pk_table = {}
+ for constraint in temp:
+ val={
+ 'primary_key' : True
+ }
+ pk_table[constraint[2]] = constraint[0]
+
+ id_to_write=filter(lambda x : (int(cols[x][1])==int(tables[constraint[0]])and(constraint[1]==cols[x][0])),cols)
+ col_id=tcol.write(cr,uid,int(id_to_write[0]),val,context)
+
+ cr_db.execute("""select
+ constraint_name,r_constraint_name from all_constraints
+ where
+ constraint_type = 'R' and owner = %s
+ """,(user))
+ constraints_map={}
+ for data in cr_db.fetchall():
+ constraints_map[data[0]]=data[1]
+
+ cr_db.execute("""select
+ table_name,column_name,constraint_name
+ from
+ all_cons_columns
+ where
+ constraint_name in (
+ select constraint_name from all_constraints
+ where
+ constraint_type = 'R' and owner = %s)
+ """,(user))
+
+
+ temp = cr_db.fetchall()
+ for constraint in temp:
+ rel_constraint_name=constraints_map[constraint[2]]
+ req_table = pk_table[rel_constraint_name]
+ val={
+ 'related_to' : tables[req_table]
+ }
+ id_to_write=filter(lambda x:(int(cols[x][1])==int(tables[constraint[0]])and (constraint[1]==cols[x][0])),cols)
+ col_id=tcol.write(cr,uid,int(id_to_write[0]),val,context)
+
+ pooler.get_pool(cr.dbname).get('olap.fact.database').write(cr,uid,[id_db],{'loaded':True})
+ wf_service = netsvc.LocalService('workflow')
+ wf_service.trg_validate(uid, 'olap.schema', part['id'], 'dbload', cr)
+ return {}
+
+def _getdata(self,cr,uid,part,context={}):
+ lines=pooler.get_pool(cr.dbname).get('olap.schema').browse(cr, uid, part['id'],context)
+ part['form']['fact_table']=lines.database_id.name
+ part['form']['db_name']=lines.database_id.db_name
+ return part['form']
+
+class wizard_data_loader(wizard.interface):
+ states = {
+ 'init': {
+ 'actions': [_getdata],
+ 'result': {'type':'form','arch':form1, 'fields':field1, 'state':[('end','Cancel'),('ok','Load Database Structure')]}
+ },
+ 'ok': {
+ 'actions': [olap_db_connect],
+ 'result': {'type':'form','arch':info,'fields':{}, 'state':[('end','Continue and Configure Structure')]}
+ },
+ 'info': {
+ 'actions': [],
+ 'result': {'type':'form', 'arch':info, 'fields':{}, 'state':[('end','Ok')]}
+ },
+ }
+wizard_data_loader('olap.load.table')
+
+# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
diff --git a/addons/olap/wizard/wizard_query_builder.py b/addons/olap/wizard/wizard_query_builder.py
new file mode 100755
index 00000000000..3b69c1cf996
--- /dev/null
+++ b/addons/olap/wizard/wizard_query_builder.py
@@ -0,0 +1,240 @@
+##############################################################################
+#
+# Copyright (c) 2005-2006 TINY SPRL. (http://tiny.be) All Rights Reserved.
+#
+# WARNING: This program as such is intended to be used by professional
+# programmers who take the whole responsability of assessing all potential
+# consequences resulting from its eventual inadequacies and bugs
+# End users who are looking for a ready-to-use solution with commercial
+# garantees and support are strongly adviced to contract a Free Software
+# Service Company
+#
+# This program is Free Software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# 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 General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+##############################################################################
+
+import wizard
+import threading
+import pooler
+from osv import osv
+import optparse
+import xmlrpclib
+import time
+
+import netsvc
+
+
+
+class Log:
+ def __init__(self):
+ self.content= ""
+ self.error= False
+ def add(self,s,error=True):
+ self.content= self.content + s
+ if error:
+ self.error= error
+ def __call__(self):
+ return self.content
+
+
+def get_cube(self, cr, uid, context):
+ pool = pooler.get_pool(cr.dbname).get('olap.cube')
+ ids = pool.search(cr, uid, [])
+ res = pool.read(cr, uid, ids, ['schema_id','name'], context)
+ res=[(r['schema_id'], r['name']) for r in res]
+
+ return res
+
+def get_details(self, cr, uid,data, context):
+ """
+ To Fetch dimension of selected schema
+ """
+ pool = pooler.get_pool(cr.dbname).get('olap.cube')
+
+ search_id=data['form']['cube_schema'][0]
+
+ ids=pool.search(cr,uid,[('schema_id','=',search_id)])
+
+ """
+ ids now have the cube id from schema user selected
+ """
+
+ """
+ To Fetch hiearchy of selected schema
+ """
+ pool = pooler.get_pool(cr.dbname).get('olap.dimension')
+
+ id_dimension=pool.search(cr,uid,[('cube_id','=',ids[0])])
+ res=pool.read(cr,uid,id_dimension,['id','name'],context)
+ log_d=Log()
+ for r in res:
+ log_d.add(r['name'])
+ log_d.add("\n")
+
+
+ """
+ To Fetch hiearchy id
+ """
+ pool=pooler.get_pool(cr.dbname).get('olap.hierarchy')
+
+ id_hierarchy=pool.search(cr,uid,[('dimension_id','in',tuple(id_dimension))])
+ res=pool.read(cr,uid,id_hierarchy,['id','name'],context)
+ log_h=Log()
+ for r in res:
+ log_h.add(r['name'])
+ log_h.add("\n")
+
+
+
+ """
+ To fetch level id
+ """
+ pool=pooler.get_pool(cr.dbname).get('olap.level')
+ id_level=pool.search(cr,uid,[('hierarchy_id','in',tuple(id_hierarchy))])
+ res=pool.read(cr,uid,id_level,['id','name'],context)
+ log_l=Log()
+ for r in res:
+ log_l.add(r['name'])
+ log_l.add("\n")
+
+ """
+ To fetch measures id
+ """
+ pool=pooler.get_pool(cr.dbname).get('olap.measure')
+ id_level=pool.search(cr,uid,[('cube_id','in',tuple(ids))])
+ res=pool.read(cr,uid,id_level,['id','name'],context)
+ log_m=Log()
+ for r in res:
+ log_m.add(r['name'])
+ log_m.add("\n")
+
+
+ return {'hierarchy':log_h(),'dimension':log_d(),'level':log_l(),'measure':log_m()}
+
+
+
+
+query_builder_form = """
+
''')
+ _connection_arch.string = '\n'.join(_arch)
+
+ return {}
+
+
+
+class wizard_test_connection(wizard.interface):
+ states = {
+ 'init': {
+ 'actions': [_test_connection],
+ 'result': {'type':'form', 'arch': _connection_arch, 'fields':{}, 'state':[('end','Ok')]}
+ },
+ }
+wizard_test_connection('olap.fact.database.test_connection')
diff --git a/addons/olap_crm/__init__.py b/addons/olap_crm/__init__.py
new file mode 100755
index 00000000000..40d842dcc48
--- /dev/null
+++ b/addons/olap_crm/__init__.py
@@ -0,0 +1,22 @@
+# -*- encoding: utf-8 -*-
+##############################################################################
+#
+# OpenERP, Open Source Management Solution
+# Copyright (C) 2004-2009 Tiny SPRL ().
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as
+# published by the Free Software Foundation, either version 3 of the
+# License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see .
+#
+##############################################################################
+
+import olap_crm
\ No newline at end of file
diff --git a/addons/olap_crm/__terp__.py b/addons/olap_crm/__terp__.py
new file mode 100644
index 00000000000..794b65138b4
--- /dev/null
+++ b/addons/olap_crm/__terp__.py
@@ -0,0 +1,37 @@
+# -*- encoding: utf-8 -*-
+##############################################################################
+#
+# OpenERP, Open Source Management Solution
+# Copyright (C) 2004-2009 Tiny SPRL ().
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as
+# published by the Free Software Foundation, either version 3 of the
+# License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see .
+#
+##############################################################################
+
+{
+ "name" : "olap_crm",
+ "version" : "0.1",
+ "author" : "Tiny",
+ "website" : "http://www.openerp.com",
+ "depends" : ["olap"],
+ "category" : "Generic Modules/Olap",
+ "description": """
+ Sale module will load the data in olap tables
+ """,
+ "init_xml" : ['olap_data.xml'],
+ "update_xml" :[],
+ "demo_xml" : ['olap_crm.xml'],
+ "active": False,
+ "installable": True
+}
diff --git a/addons/olap_crm/i18n/fr_BE.po b/addons/olap_crm/i18n/fr_BE.po
new file mode 100644
index 00000000000..f93a3dfa8e2
--- /dev/null
+++ b/addons/olap_crm/i18n/fr_BE.po
@@ -0,0 +1,29 @@
+# Translation of OpenERP Server.
+# This file contains the translation of the following modules:
+# * olap_crm
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: OpenERP Server 5.0.6\n"
+"Report-Msgid-Bugs-To: support@openerp.com\n"
+"POT-Creation-Date: 2009-11-26 05:29:03+0000\n"
+"PO-Revision-Date: 2009-11-26 05:29:03+0000\n"
+"Last-Translator: <>\n"
+"Language-Team: \n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: \n"
+"Plural-Forms: \n"
+
+#. module: olap_crm
+#: model:ir.module.module,description:olap_crm.module_meta_information
+msgid "\n"
+" Sale module will load the data in olap tables\n"
+" "
+msgstr ""
+
+#. module: olap_crm
+#: model:ir.module.module,shortdesc:olap_crm.module_meta_information
+msgid "olap_crm"
+msgstr ""
+
diff --git a/addons/olap_crm/i18n/olap_crm.pot b/addons/olap_crm/i18n/olap_crm.pot
new file mode 100644
index 00000000000..f93a3dfa8e2
--- /dev/null
+++ b/addons/olap_crm/i18n/olap_crm.pot
@@ -0,0 +1,29 @@
+# Translation of OpenERP Server.
+# This file contains the translation of the following modules:
+# * olap_crm
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: OpenERP Server 5.0.6\n"
+"Report-Msgid-Bugs-To: support@openerp.com\n"
+"POT-Creation-Date: 2009-11-26 05:29:03+0000\n"
+"PO-Revision-Date: 2009-11-26 05:29:03+0000\n"
+"Last-Translator: <>\n"
+"Language-Team: \n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: \n"
+"Plural-Forms: \n"
+
+#. module: olap_crm
+#: model:ir.module.module,description:olap_crm.module_meta_information
+msgid "\n"
+" Sale module will load the data in olap tables\n"
+" "
+msgstr ""
+
+#. module: olap_crm
+#: model:ir.module.module,shortdesc:olap_crm.module_meta_information
+msgid "olap_crm"
+msgstr ""
+
diff --git a/addons/olap_crm/olap_crm.xml b/addons/olap_crm/olap_crm.xml
new file mode 100755
index 00000000000..96dadb7d783
--- /dev/null
+++ b/addons/olap_crm/olap_crm.xml
@@ -0,0 +1,462 @@
+
+
+
+
+
+
+
+ Open ERP CRM Database
+ crm
+ postgres
+ postgres
+
+
+
+ OpenERPCRM
+ none
+
+
+
+
+
+
+
+
+ crm_case
+ crm_case
+
+ True
+
+
+
+ crm_case_categ
+ crm_case_categ
+
+ True
+
+
+
+ crm_case_stage
+ crm_case_stage
+
+ True
+
+
+
+ res_partner
+ res_partner
+
+ True
+
+
+
+ crm_case_section
+ crm_case_section
+
+ True
+
+
+ res_partner_canal
+ res_partner_canal
+
+ True
+
+
+
+
+
+
+ id
+ id
+ int4
+
+ True
+ True
+
+
+ planned_revenue
+ planned_revenue
+ float8
+
+ True
+
+
+ parnter_id
+ partner_id
+ float8
+
+ True
+
+
+
+
+ id
+ id
+ float8
+
+ True
+
+
+ probability
+ probability
+ float8
+
+ True
+
+
+ state
+ state
+ varchar
+
+ True
+
+
+
+ name
+ name
+ varchar
+
+ True
+
+
+
+
+
+
+
+ categ_id
+ categ_id
+ int4
+
+
+
+
+
+ partner_id
+ partner_id
+ int4
+
+
+
+
+
+ canal_id
+ canal_id
+ int4
+
+
+
+
+
+
+ name
+ name
+ varchar
+
+
+
+
+ name
+ name
+ varchar
+
+
+
+ name
+ name
+ varchar
+
+
+
+
+ stage_id
+ stage_id
+ int4
+
+
+
+
+
+ section_id
+ section_id
+ int4
+
+
+
+
+
+ name
+ name
+ varchar
+
+
+
+
+
+
+
+
+
+ crm_cube
+
+
+
+
+
+
+ crm_cube_section
+
+
+
+
+
+ crm_cube_stage_parnter
+
+
+
+
+ crm_cube_parnter
+
+
+
+
+
+
+ crm_cube_categ
+
+
+
+
+
+ crm_cube_channel
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ CRM
+
+
+
+
+
+
+
+ Sections
+
+
+
+
+
+ Sections
+
+
+
+
+
+ Sections
+
+ name
+ crm_case_section
+
+ 1
+
+
+
+ States
+
+ name
+ crm_case_stage
+
+ 2
+
+
+
+
+
+ States
+
+
+
+
+
+ States
+
+
+
+
+
+ States
+
+ state
+ crm_case
+
+ 1
+
+
+
+ States
+
+ name
+ crm_case_stage
+
+ 2
+
+
+
+
+
+
+ Category
+
+
+
+
+
+ Category
+
+ crm_case
+
+
+
+
+ name
+
+ name
+ crm_case_categ
+
+
+
+
+
+ Customer
+
+
+
+
+ Customer
+
+ crm_case
+
+
+
+
+ name
+
+ name
+ res_partner
+
+
+
+
+
+
+ Channels
+
+
+
+
+
+ Channel
+
+
+
+
+
+ Channel
+
+ name
+ res_partner_canal
+
+ 1
+
+
+
+
+
+
+
+ Total Cases
+
+ sql_expr
+ count(crm_case.id)
+
+
+
+ Average Planned Revenue
+
+ sql_expr
+ avg(crm_case.planned_revenue)
+ cr_postfix_comma
+
+
+
+ Average Planned Cost
+
+ sql_expr
+ avg(crm_case.planned_cost)
+ cr_postfix_comma
+
+
+
+ Planned Revenue
+
+
+ planned_cost
+ crm_case
+ sum
+ cr_postfix_comma
+
+
+
+ Planned Revenue
+
+
+ planned_revenue
+ crm_case
+ sum
+
+
+
+ Probability
+
+
+ probability
+ crm_case
+ sum
+
+d
+
+
+
diff --git a/addons/olap_crm/olap_data.xml b/addons/olap_crm/olap_data.xml
new file mode 100755
index 00000000000..d36ec6161fe
--- /dev/null
+++ b/addons/olap_crm/olap_data.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
diff --git a/addons/olap_extract/__init__.py b/addons/olap_extract/__init__.py
new file mode 100755
index 00000000000..8ec082d25fb
--- /dev/null
+++ b/addons/olap_extract/__init__.py
@@ -0,0 +1,23 @@
+# -*- encoding: utf-8 -*-
+##############################################################################
+#
+# OpenERP, Open Source Management Solution
+# Copyright (C) 2004-2009 Tiny SPRL ().
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as
+# published by the Free Software Foundation, either version 3 of the
+# License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see .
+#
+##############################################################################
+
+import olap_extract
+import wizard_olap_extract
\ No newline at end of file
diff --git a/addons/olap_extract/__terp__.py b/addons/olap_extract/__terp__.py
new file mode 100644
index 00000000000..6e44d5e7e43
--- /dev/null
+++ b/addons/olap_extract/__terp__.py
@@ -0,0 +1,37 @@
+# -*- encoding: utf-8 -*-
+##############################################################################
+#
+# OpenERP, Open Source Management Solution
+# Copyright (C) 2004-2009 Tiny SPRL ().
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as
+# published by the Free Software Foundation, either version 3 of the
+# License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see .
+#
+##############################################################################
+
+{
+ "name" : "Module to extracts the schema structure",
+ "version" : "0.1",
+ "author" : "Tiny",
+ "website" : "http://www.openerp.com",
+ "depends" : ["olap"],
+ "category" : "Generic Modules/Olap",
+ "description": """
+ Extracts the schema structure.
+ """,
+ "init_xml" : [],
+ "update_xml" : ["olap_extract_wizard.xml"],
+ "demo_xml" : [],
+ "active": False,
+ "installable": True
+}
diff --git a/addons/olap_extract/i18n/fr_BE.po b/addons/olap_extract/i18n/fr_BE.po
new file mode 100644
index 00000000000..92f455fcebd
--- /dev/null
+++ b/addons/olap_extract/i18n/fr_BE.po
@@ -0,0 +1,54 @@
+# Translation of OpenERP Server.
+# This file contains the translation of the following modules:
+# * olap_extract
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: OpenERP Server 5.0.6\n"
+"Report-Msgid-Bugs-To: support@openerp.com\n"
+"POT-Creation-Date: 2009-11-26 05:29:21+0000\n"
+"PO-Revision-Date: 2009-11-26 05:29:21+0000\n"
+"Last-Translator: <>\n"
+"Language-Team: \n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: \n"
+"Plural-Forms: \n"
+
+#. module: olap_extract
+#: model:ir.module.module,shortdesc:olap_extract.module_meta_information
+msgid "olap_extract"
+msgstr ""
+
+#. module: olap_extract
+#: wizard_button:olap.extract.schema,init,ok:0
+msgid "OK"
+msgstr ""
+
+#. module: olap_extract
+#: model:ir.actions.wizard,name:olap_extract.bi_olap_extract_schema
+msgid "Olap Extract"
+msgstr ""
+
+#. module: olap_extract
+#: model:ir.module.module,description:olap_extract.module_meta_information
+msgid "\n"
+" Extracts the schema structure.\n"
+" "
+msgstr ""
+
+#. module: olap_extract
+#: wizard_field:olap.extract.schema,init,module_name:0
+msgid "Module Name"
+msgstr ""
+
+#. module: olap_extract
+#: wizard_button:olap.extract.schema,init,end:0
+msgid "Cancel"
+msgstr ""
+
+#. module: olap_extract
+#: wizard_view:olap.extract.schema,init:0
+msgid "New Module Name"
+msgstr ""
+
diff --git a/addons/olap_extract/i18n/olap_extract.pot b/addons/olap_extract/i18n/olap_extract.pot
new file mode 100644
index 00000000000..92f455fcebd
--- /dev/null
+++ b/addons/olap_extract/i18n/olap_extract.pot
@@ -0,0 +1,54 @@
+# Translation of OpenERP Server.
+# This file contains the translation of the following modules:
+# * olap_extract
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: OpenERP Server 5.0.6\n"
+"Report-Msgid-Bugs-To: support@openerp.com\n"
+"POT-Creation-Date: 2009-11-26 05:29:21+0000\n"
+"PO-Revision-Date: 2009-11-26 05:29:21+0000\n"
+"Last-Translator: <>\n"
+"Language-Team: \n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: \n"
+"Plural-Forms: \n"
+
+#. module: olap_extract
+#: model:ir.module.module,shortdesc:olap_extract.module_meta_information
+msgid "olap_extract"
+msgstr ""
+
+#. module: olap_extract
+#: wizard_button:olap.extract.schema,init,ok:0
+msgid "OK"
+msgstr ""
+
+#. module: olap_extract
+#: model:ir.actions.wizard,name:olap_extract.bi_olap_extract_schema
+msgid "Olap Extract"
+msgstr ""
+
+#. module: olap_extract
+#: model:ir.module.module,description:olap_extract.module_meta_information
+msgid "\n"
+" Extracts the schema structure.\n"
+" "
+msgstr ""
+
+#. module: olap_extract
+#: wizard_field:olap.extract.schema,init,module_name:0
+msgid "Module Name"
+msgstr ""
+
+#. module: olap_extract
+#: wizard_button:olap.extract.schema,init,end:0
+msgid "Cancel"
+msgstr ""
+
+#. module: olap_extract
+#: wizard_view:olap.extract.schema,init:0
+msgid "New Module Name"
+msgstr ""
+
diff --git a/addons/olap_extract/olap_extract_wizard.xml b/addons/olap_extract/olap_extract_wizard.xml
new file mode 100755
index 00000000000..7de48f3c7ac
--- /dev/null
+++ b/addons/olap_extract/olap_extract_wizard.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
diff --git a/addons/olap_extract/wizard_olap_extract.py b/addons/olap_extract/wizard_olap_extract.py
new file mode 100755
index 00000000000..e71d2cb7fe6
--- /dev/null
+++ b/addons/olap_extract/wizard_olap_extract.py
@@ -0,0 +1,249 @@
+# -*- encoding: utf-8 -*-
+##############################################################################
+#
+# OpenERP, Open Source Management Solution
+# Copyright (C) 2004-2009 Tiny SPRL ().
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as
+# published by the Free Software Foundation, either version 3 of the
+# License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see .
+#
+##############################################################################
+
+import wizard
+import pooler
+import csv
+import os
+import time
+import netsvc
+import zipfile
+
+
+form1 = '''
+
+
+
'''
+
+field1 = {
+ 'module_name': {'string':'Module Name', 'type':'char','size':'64', 'required':True},
+}
+
+
+class wizard_olap_extract(wizard.interface):
+
+ def zipper(self,zipname,filename,mode="a"):
+ z = zipfile.ZipFile(zipname+".zip", mode)
+ z.write(filename)
+ print "\n",z.printdir()
+
+
+ def write_csv(self,filename,content=[]):
+ fid = open(filename, 'w')
+ if fid == -1:
+ print 'File: temp.csv not found or could not be opened'
+ return False
+ else:
+ writer=csv.writer(fid, 'TINY',delimiter=',')
+ for row in content:
+ writer.writerow(row)
+ fid.close
+ return True
+
+ def table_depth(self,cr,uid,list=[],context={}):
+
+ res={}
+ templeft={}
+ tempright={}
+ for table_id in list:
+ lines=pooler.get_pool(cr.dbname).get('olap.cube.table').browse(cr, uid,table_id,context)
+ res[str(lines.id)] = ["cubetable_"+str(lines.id),lines.name and lines.name or '',lines.table_alias and lines.table_alias or '',lines.key_left and lines.key_left or '',lines.key_right and lines.key_right or '',lines.table_left_id.id and "cubetable_"+str(lines.table_left_id.id) or '',lines.table_right_id.id and "cubetable_"+str(lines.table_right_id.id) or '']
+ if(lines.table_left_id.id):
+ templeft = self.table_depth(cr,uid,[lines.table_left_id.id],context)
+
+ if templeft:
+ for temp in templeft:
+ if not res.has_key(temp):
+ res[temp]= templeft[temp]
+
+
+ if(lines.table_right_id.id):
+ tempright = self.table_depth(cr,uid,[lines.table_right_id.id],context)
+
+ if tempright:
+ for temp in tempright:
+ if not res.has_key(temp):
+ res[temp]= tempright[temp]
+ return res
+
+
+ def _extract_schema(self, cr, uid, data, context={}):
+
+ _name = data['form']['module_name']
+ _modulename = "olap_"+_name
+
+ dirname = _modulename
+ if not os.path.isdir("./addons/" + dirname + "/"):
+ os.mkdir("./addons/" + dirname + "/")
+
+ os.chdir("./addons/"+dirname)
+
+ _init = "import %s" % _modulename
+ f = open("__init__.py","w")
+ f.write(_init)
+ f.close()
+ self.zipper(_modulename, "__init__.py","w")
+
+ _init_files = {
+ "1":"olap.fact.database.csv",
+ "2":"olap.schema.csv",
+ "5":"olap.cube.table.csv",
+ "6":"olap.cube.csv",
+ "7":"olap.dimension.csv",
+ "8":"olap.hierarchy.csv",
+ "9":"olap.level.csv",
+ "10":"olap.measure.csv"
+ }
+ _init_xml = """"%(1)s",
+ "%(2)s",
+ "%(5)s",
+ "%(6)s",
+ "%(7)s",
+ "%(8)s",
+ "%(9)s",
+ "%(10)s",
+ """ % _init_files
+
+ data['modulename'] = _modulename
+ data['init_xml'] = _init_xml
+
+ _terp= """{
+ "name" : "%(modulename)s",
+ "version" : "0.1",
+ "author" : "Tiny",
+ "website" : "http://tinyerp.com/",
+ "depends" : ["olap"],
+ "category" : "Generic Modules/Others",
+ "description": "Module will load the data in olap tables",
+ "init_xml" :[
+ %(init_xml)s
+ ],
+ "update_xml" : [],
+ "demo_xml" : [],
+ "active": False,
+ "installable": True
+ }"""%data
+
+ f = open("__terp__.py","w")
+ f.write(_terp)
+ f.close()
+ self.zipper(_modulename, "__terp__.py")
+
+
+ schema_id = data['id']
+
+ lines=pooler.get_pool(cr.dbname).get('olap.schema').browse(cr, uid, schema_id,context)
+
+ _extract=[]
+ _extract.append(['id','name','db_name','db_login','db_password'])
+ _extract.append(["db_"+str(lines.database_id.id),lines.database_id.name,lines.database_id.db_name,lines.database_id.db_login,lines.database_id.db_password])
+ self.write_csv('olap.fact.database.csv',_extract)
+ self.zipper(_modulename, "olap.fact.database.csv")
+
+ _extract=[]
+ _extract.append(['id','name','database_id:id','loaded','configure','ready','state','note'])
+ _extract.append(["schema_"+str(lines.id),lines.name,"db_"+str(lines.database_id.id),lines.loaded and lines.loaded or '',lines.configure and lines.configure or '', lines.ready and lines.ready or '',lines.state,lines.note and lines.note or ''])
+ self.write_csv('olap.schema.csv',_extract)
+ self.zipper(_modulename, "olap.schema.csv")
+
+ cube_ids = lines.cube_ids
+ _extractcubes=[]
+ _extractcubes.append(['id','name','table_id:id','schema_id:id'])
+
+ _extractmeasures=[]
+ _extractmeasures.append(['id','name','cube_id:id','value_column','value_sql','agregator','datatype','formatstring'])
+
+ _extractdimension=[]
+ _extractdimension.append(['id','name','foreign_key','foreign_key_table','cube_id:id'])
+
+ _extracthiers=[]
+ _extracthiers.append(['id','name','primary_key','primary_key_table','field_name','member_all','member_default','sequence','type','dimension_id:id','table_id:id'])
+
+ _extractlevels=[]
+ _extractlevels.append(['id','name','column_name','column_id_name','type','table_name','sequence','hierarchy_id:id'])
+
+ _cube_table_ids = []
+ for cube in cube_ids:
+ _extractcubes.append(["cube_"+str(cube.id),cube.name,"cubetable_"+str(cube.table_id.id),"schema_"+str(cube.schema_id.id)])
+ _cube_table_ids.append(cube.table_id.id)
+
+ measure_ids = cube.measure_ids
+ for measure in measure_ids:
+ _extractmeasures.append(["msr_"+str(measure.id),measure.name,"cube_"+str(measure.cube_id.id),measure.value_column and measure.value_column or '',measure.value_sql and measure.value_sql or '',measure.agregator,measure.datatype and measure.datatype or '',measure.formatstring])
+
+ dimension_ids = cube.dimension_ids
+ for dimension in dimension_ids:
+ _extractdimension.append(["dim_"+str(dimension.id),dimension.name,dimension.foreign_key and dimension.foreign_key or '',dimension.foreign_key_table and dimension.foreign_key_table or '',"cube_"+str(dimension.cube_id.id)])
+
+ hiers_ids = dimension.hierarchy_ids
+ for hier in hiers_ids:
+ _extracthiers.append(["hier_"+str(hier.id),hier.name,hier.primary_key,hier.primary_key_table and hier.primary_key_table or '',hier.field_name,hier.member_all,hier.member_default,hier.sequence,hier.type,"dim_"+str(hier.dimension_id.id),"cubetable_"+str(hier.table_id.id)])
+ _cube_table_ids.append(hier.table_id.id)
+
+ level_ids = hier.level_ids
+ for level in level_ids:
+ _extractlevels.append(["lvl_"+str(level.id),level.name,level.column_name,level.column_id_name,level.type,level.table_name,level.sequence,"hier_"+str(level.hierarchy_id.id)])
+
+ res={}
+ _extract=[]
+ _extract.append(['id','name','table_alias','key_left','key_right','table_left_id:id','table_right_id:id'])
+ res = self.table_depth(cr,uid,_cube_table_ids,context)
+ key = res.keys()
+ key = map(lambda x: int(x),key)
+ key.sort()
+
+ for k in key:
+ _extract.append(res[str(k)])
+
+ self.write_csv('olap.cube.csv',_extractcubes)
+ self.zipper(_modulename, "olap.cube.csv")
+
+ self.write_csv('olap.measure.csv',_extractmeasures)
+ self.zipper(_modulename, "olap.measure.csv")
+
+ self.write_csv('olap.dimension.csv',_extractdimension)
+ self.zipper(_modulename, "olap.dimension.csv")
+
+ self.write_csv('olap.hierarchy.csv',_extracthiers)
+ self.zipper(_modulename, "olap.hierarchy.csv")
+
+ self.write_csv('olap.level.csv',_extractlevels)
+ self.zipper(_modulename, "olap.level.csv")
+
+ self.write_csv('olap.cube.table.csv',_extract)
+ self.zipper(_modulename, "olap.cube.table.csv")
+
+ return {}
+
+ states = {
+
+ 'init': {
+ 'actions': [],
+ 'result': {'type':'form','arch':form1, 'fields':field1, 'state':[('end','Cancel'),('ok','OK')]}
+ },
+
+ 'ok' : {
+ 'actions' : [],
+ 'result' : {'type' : 'action' ,'action':_extract_schema,'state':'end'}
+ }
+ }
+
+wizard_olap_extract('olap.extract.schema')
diff --git a/addons/olap_sale/__init__.py b/addons/olap_sale/__init__.py
new file mode 100755
index 00000000000..5d7667acf15
--- /dev/null
+++ b/addons/olap_sale/__init__.py
@@ -0,0 +1,22 @@
+# -*- encoding: utf-8 -*-
+##############################################################################
+#
+# OpenERP, Open Source Management Solution
+# Copyright (C) 2004-2009 Tiny SPRL ().
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as
+# published by the Free Software Foundation, either version 3 of the
+# License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see .
+#
+##############################################################################
+
+import olap_sale
\ No newline at end of file
diff --git a/addons/olap_sale/__terp__.py b/addons/olap_sale/__terp__.py
new file mode 100644
index 00000000000..d94e6ee956d
--- /dev/null
+++ b/addons/olap_sale/__terp__.py
@@ -0,0 +1,37 @@
+# -*- encoding: utf-8 -*-
+##############################################################################
+#
+# OpenERP, Open Source Management Solution
+# Copyright (C) 2004-2009 Tiny SPRL ().
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as
+# published by the Free Software Foundation, either version 3 of the
+# License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see .
+#
+##############################################################################
+
+{
+ "name" : "Load Sale Module data in Olap Tables",
+ "version" : "0.1",
+ "author" : "Tiny",
+ "website" : "http://www.openerp.com",
+ "depends" : ["olap"],
+ "category" : "Generic Modules/Olap",
+ "description": """
+ Sale module will load the data in olap tables
+ """,
+ "init_xml" : ['olap_data.xml'],
+ "update_xml" :[],
+ "demo_xml" : ['olap_sale.xml'],
+ "active": False,
+ "installable": True
+}
diff --git a/addons/olap_sale/i18n/fr_BE.po b/addons/olap_sale/i18n/fr_BE.po
new file mode 100644
index 00000000000..a9f03334ab3
--- /dev/null
+++ b/addons/olap_sale/i18n/fr_BE.po
@@ -0,0 +1,29 @@
+# Translation of OpenERP Server.
+# This file contains the translation of the following modules:
+# * olap_sale
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: OpenERP Server 5.0.6\n"
+"Report-Msgid-Bugs-To: support@openerp.com\n"
+"POT-Creation-Date: 2009-11-26 05:29:36+0000\n"
+"PO-Revision-Date: 2009-11-26 05:29:36+0000\n"
+"Last-Translator: <>\n"
+"Language-Team: \n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: \n"
+"Plural-Forms: \n"
+
+#. module: olap_sale
+#: model:ir.module.module,description:olap_sale.module_meta_information
+msgid "\n"
+" Sale module will load the data in olap tables\n"
+" "
+msgstr ""
+
+#. module: olap_sale
+#: model:ir.module.module,shortdesc:olap_sale.module_meta_information
+msgid "olap_sale"
+msgstr ""
+
diff --git a/addons/olap_sale/i18n/olap_sale.pot b/addons/olap_sale/i18n/olap_sale.pot
new file mode 100644
index 00000000000..a9f03334ab3
--- /dev/null
+++ b/addons/olap_sale/i18n/olap_sale.pot
@@ -0,0 +1,29 @@
+# Translation of OpenERP Server.
+# This file contains the translation of the following modules:
+# * olap_sale
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: OpenERP Server 5.0.6\n"
+"Report-Msgid-Bugs-To: support@openerp.com\n"
+"POT-Creation-Date: 2009-11-26 05:29:36+0000\n"
+"PO-Revision-Date: 2009-11-26 05:29:36+0000\n"
+"Last-Translator: <>\n"
+"Language-Team: \n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: \n"
+"Plural-Forms: \n"
+
+#. module: olap_sale
+#: model:ir.module.module,description:olap_sale.module_meta_information
+msgid "\n"
+" Sale module will load the data in olap tables\n"
+" "
+msgstr ""
+
+#. module: olap_sale
+#: model:ir.module.module,shortdesc:olap_sale.module_meta_information
+msgid "olap_sale"
+msgstr ""
+
diff --git a/addons/olap_sale/olap_data.xml b/addons/olap_sale/olap_data.xml
new file mode 100755
index 00000000000..d36ec6161fe
--- /dev/null
+++ b/addons/olap_sale/olap_data.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
diff --git a/addons/olap_sale/olap_sale.xml b/addons/olap_sale/olap_sale.xml
new file mode 100644
index 00000000000..42b6b327dc9
--- /dev/null
+++ b/addons/olap_sale/olap_sale.xml
@@ -0,0 +1,753 @@
+
+
+
+
+
+
+
+ OpenERP Sales Databases
+ sales
+ postgres
+ postgres
+
+
+
+ OpenERPSales
+ none
+
+
+
+
+
+
+ sale_order_line
+ sale_order_line
+
+ True
+
+
+
+ sale_order
+ sale_order
+
+ True
+
+
+
+ product_product
+ product_product
+
+ True
+
+
+
+ product_template
+ product_template
+
+ True
+
+
+
+ product_category
+ product_category
+
+ True
+
+
+ res_partner_address
+ res_partner_address
+
+ True
+
+
+
+ res_country
+ res_country
+
+ True
+
+
+
+ res_users
+ res_users
+
+ True
+
+
+
+ res_partner
+ res_partner
+
+ True
+
+
+
+ product_id
+ product_id
+ int4
+
+
+ True
+
+
+
+ id
+ id
+ int4
+
+ True
+ True
+
+
+
+ id
+ id
+ varchar
+
+ True
+ True
+
+
+
+ id
+ id
+ int4
+
+ True
+ True
+
+
+
+ id
+ id
+ int4
+
+ True
+ True
+
+
+
+ amount_total
+ amount_total
+ float8
+
+ True
+
+
+
+ name
+ name
+ varchar
+
+ True
+
+
+
+ name
+ name
+ varchar
+
+ True
+
+
+
+ categ_id
+ categ_id
+ int4
+
+
+ True
+
+
+
+ name
+ name
+ varchar
+
+ True
+
+
+
+ city
+ city
+ varchar
+
+ True
+
+
+ name
+ name
+ varchar
+
+ True
+
+
+
+ product_tmpl_id
+ product_tmpl_id
+ varchar
+
+
+ True
+
+
+
+ id
+ id
+ int4
+
+ True
+ True
+
+
+
+ id
+ id
+ int4
+
+ True
+ True
+
+
+
+ default_code
+ default_code
+ varchar
+
+ True
+
+
+
+ date_order
+ date_order
+ date
+
+ True
+
+
+
+ product_uom_qty
+ product_uom_qty
+ int4
+
+ True
+
+
+
+ price_unit
+ price_unit
+ int4
+
+ True
+
+
+
+ id
+ id
+ int4
+
+ True
+ True
+
+
+
+
+ order_id
+ order_id
+ int4
+
+
+ True
+
+
+
+ partner_id
+ partner_id
+ int4
+
+
+ True
+
+
+
+ id
+ id
+ int4
+
+ True
+ True
+
+
+
+ id
+ id
+ int4
+
+ True
+ True
+
+
+
+ name
+ name
+ varchar
+
+ True
+
+
+
+ id
+ id
+ int4
+
+ True
+ True
+
+
+
+ id
+ id
+ int4
+
+ True
+ True
+
+
+
+ partner_order_id
+ partner_order_id
+ int4
+
+
+ True
+
+
+
+ name
+ name
+ varchar
+
+ True
+
+
+
+ name
+ name
+ varchar
+
+ True
+
+
+
+ country_id
+ country_id
+ int4
+
+
+ True
+
+
+
+ city
+ city
+ varchar
+
+ True
+
+
+
+ order_id
+ order_id
+ int4
+
+
+ True
+
+
+
+
+ product_uom_qty
+ product_uom_qty
+ numeric
+
+ True
+
+
+
+ price_unit
+ price_unit
+ numeric
+
+ True
+
+
+
+ create_uid
+ create_uid
+ int4
+
+
+ True
+
+
+
+
+
+ Sales
+
+
+
+
+
+ Product Category
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Sale Product
+
+
+
+
+
+ Sale Country
+
+
+
+
+
+
+ sale_order_line
+
+
+
+
+ sale_order_line
+
+
+
+
+
+ sale_order_line
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Sales
+
+
+
+
+
+
+
+ All Products
+
+
+
+
+ All Products
+
+ product_product
+
+
+
+
+ Product Code
+
+ default_code
+ product_product
+
+
+
+
+ Products by Category
+
+
+
+
+ Products Category
+
+ product_product
+
+
+
+
+ Product Category
+
+ name
+ product_category
+
+
+
+
+ Product
+
+ name
+ product_template
+
+
+
+
+ Order Date
+
+
+
+
+ Order Date
+
+ sale_order
+
+
+
+
+ date_order
+
+ date_order
+ date_year
+ 1
+ sale_order
+
+
+
+
+ date_order
+
+ date_order
+ date_quarter
+ 2
+ sale_order
+
+
+
+
+ date_order
+
+ date_order
+ date_month
+ 3
+ sale_order
+
+
+
+
+
+
+ Country
+
+
+
+
+ Partner Country
+
+ sale_order
+
+
+
+
+ country_id
+
+ name
+ res_country
+
+
+
+
+
+
+ Sales by Partner City
+
+
+
+
+ City
+
+ sale_order
+
+
+
+
+ city
+ 1
+
+ city
+ res_partner_address
+
+
+
+
+ name
+ 2
+
+ name
+ res_partner
+
+
+
+
+
+
+
+
+ Users
+
+
+
+
+ Users
+
+ res_users
+
+
+
+
+ name
+
+
+ res_users
+ name
+
+
+
+
+
+
+
+
+ Average Sales
+
+
+ amount_total
+ sale_order
+ avg
+ cr_postfix
+
+
+ Total Sales
+
+
+ amount_total
+ sale_order
+ sum
+ cr_postfix_comma
+
+
+
+ Units Sold
+
+ sql_expr
+ count(sale_order.id)
+
+
+
+
+
diff --git a/addons/point_of_sale/__init__.py b/addons/point_of_sale/__init__.py
index 9d39c1a9306..1a83d3f3b44 100644
--- a/addons/point_of_sale/__init__.py
+++ b/addons/point_of_sale/__init__.py
@@ -1,21 +1,22 @@
-# -*- coding: utf-8 -*-
+# -*- encoding: utf-8 -*-
##############################################################################
-#
+#
# OpenERP, Open Source Management Solution
-# Copyright (C) 2004-2010 Tiny SPRL ().
+# Copyright (C) 2004-2009 Tiny SPRL (). All Rights Reserved
+# $Id$
#
# 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.
+# it under the terms of the GNU 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.
+# GNU 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 .
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
#
##############################################################################
@@ -23,5 +24,8 @@ import pos
import stock
import wizard
import report
+import pos_account_bank_statement
+import account_bank_statement
+
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
diff --git a/addons/point_of_sale/__terp__.py b/addons/point_of_sale/__terp__.py
index 596142c7902..0610144ca87 100644
--- a/addons/point_of_sale/__terp__.py
+++ b/addons/point_of_sale/__terp__.py
@@ -1,21 +1,22 @@
-# -*- coding: utf-8 -*-
+# -*- encoding: utf-8 -*-
##############################################################################
-#
+#
# OpenERP, Open Source Management Solution
-# Copyright (C) 2004-2010 Tiny SPRL ().
+# Copyright (C) 2004-2009 Tiny SPRL (). All Rights Reserved
+# $Id$
#
# 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.
+# it under the terms of the GNU 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.
+# GNU 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 .
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
#
##############################################################################
@@ -35,8 +36,23 @@ Main features :
""",
'author': 'Tiny',
- 'depends': ['sale', 'purchase', 'account', 'account_tax_include'],
- 'init_xml': [],
+ 'depends': ['sale', 'delivery','report_mrp'],
+# 'depends': ['sale', 'purchase', 'account', 'account_tax_include','board','mrp','board_manufacturing','delivery','profile_manufacturing','account','multi_company'],
+ 'init_xml': [
+ 'security/point_of_sale_security.xml',
+ 'security/ir.model.access.csv',
+ 'pos_report.xml',
+ 'pos_wizard.xml',
+ 'pos_view.xml',
+ 'pos_sequence.xml',
+ 'posrule_data.xml',
+ 'pos_data.xml',
+ 'pos_workflow.xml',
+ 'statement_view.xml',
+ 'statement_report.xml',
+ 'statement_data.xml',
+ 'statement_wizard.xml'
+ ],
'update_xml': [
'security/point_of_sale_security.xml',
'security/ir.model.access.csv',
@@ -44,11 +60,12 @@ Main features :
'pos_wizard.xml',
'pos_view.xml',
'pos_sequence.xml',
+ 'posrule_data.xml',
'pos_data.xml',
'pos_workflow.xml'
],
- 'demo_xml': [],
+ 'demo_xml': ['pos_demo.xml','singer_statement_demo.xml','multi_company_stock_data.xml'],
'installable': True,
- 'certificate': '0048272150909',
+ 'certificate': '',
}
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
diff --git a/addons/point_of_sale/account_bank_statement.py b/addons/point_of_sale/account_bank_statement.py
new file mode 100644
index 00000000000..b599f0531f9
--- /dev/null
+++ b/addons/point_of_sale/account_bank_statement.py
@@ -0,0 +1,215 @@
+# encoding: utf-8
+##############################################################################
+#
+# OpenERP, Open Source Management Solution
+# Copyright (C) 2004-2008 PC Solutions (). All Rights Reserved
+# $Id$
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU 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 General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
+#
+##############################################################################
+
+from osv import osv, fields
+import time
+from mx import DateTime
+from decimal import Decimal
+from tools.translate import _
+
+
+class account_journal(osv.osv):
+ _inherit = 'account.journal'
+ _columns = {
+ 'auto_cash': fields.boolean('Automatic Opening', help="This field authorize the automatic creation of the cashbox"),
+ 'special_journal':fields.boolean('Special Journal', help="Will put all the orders in waiting status till being accepted"),
+ 'check_dtls': fields.boolean('Check Details', help="This field authorize Validation of Cashbox without checking ending details"),
+ 'statement_sequence_id': fields.many2one('ir.sequence', 'Statement Sequence', \
+ help="The sequence used for statement numbers in this journal."),
+ }
+ _defaults = {
+ 'check_dtls': lambda *a:True,
+ 'auto_cash': lambda *a:True,
+ }
+account_journal()
+
+
+class singer_statement(osv.osv):
+ _name = 'singer.statement'
+ _description = 'Statements'
+
+ def _sub_total(self, cr, uid, ids, name, arg, context=None):
+ res = {}
+ for obj in self.browse(cr, uid, ids):
+ res[obj.id] = obj.pieces * obj.number
+ return res
+
+ def on_change_sub2(self, cr, uid, ids, pieces, number, *a):
+ sub=pieces*number
+ return {'value':{'subtotal': sub or 0.0}}
+
+
+ def on_change_sub(self, cr, uid, ids, pieces, number,*a):
+ sub=pieces*number
+ return {'value':{'subtotal': sub or 0.0}}
+
+ _columns = {
+ 'pieces': fields.float('Values', digits=(16,2)),
+ 'number': fields.integer('Number'),
+ 'subtotal': fields.function(_sub_total, method=True, string='Sub Total', type='float',digits=(16,2)),
+ 'starting_id': fields.many2one('account.bank.statement',ondelete='cascade'),
+ 'ending_id': fields.many2one('account.bank.statement',ondelete='cascade'),
+ }
+
+singer_statement()
+
+class account_bank_statement(osv.osv):
+ _inherit = 'account.bank.statement'
+ def _get_starting_balance(self, cr, uid, ids, name, arg, context=None):
+ res ={}
+ for statement in self.browse(cr, uid, ids):
+ amount_total=0.0
+ for line in statement.starting_details_ids:
+ amount_total+= line.pieces * line.number
+ res[statement.id]=amount_total
+ return res
+
+ def _get_sum_entry_encoding(self, cr, uid, ids, name, arg, context=None):
+ res2={}
+ for statement in self.browse(cr, uid, ids):
+ encoding_total=0.0
+ for line in statement.line_ids:
+ encoding_total+= line.amount
+ res2[statement.id]=encoding_total
+ return res2
+
+ def _default_journal_id(self, cr, uid, context={}):
+ company_id = self.pool.get('res.users').browse(cr, uid, uid).company_id.id
+ print [('type','=','cash'),('auto_cash','=',False), ('company_id', '=', company_id)]
+ journal = self.pool.get('account.journal').search(cr, uid, [('type', '=', 'cash'), ('auto_cash','=',False), ('company_id', '=', company_id)])
+ if journal:
+ return journal[0]
+ else:
+ return False
+
+ _columns = {
+ 'journal_id': fields.many2one('account.journal', 'Journal', required=True),
+ 'balance_start': fields.function(_get_starting_balance, method=True, string='Starting Balance', type='float',digits=(16,2)),
+ # 'balance_start': fields.float('Starting Balance',digits=(16,2)),
+ # 'balance_end': fields.float('Balance',digits=(16,2)),
+ 'state': fields.selection([('draft', 'Draft'),('confirm', 'Confirm'),('open','Open')],
+ 'State', required=True, states={'confirm': [('readonly', True)]}, readonly="1"),
+ 'total_entry_encoding':fields.function(_get_sum_entry_encoding, method=True, string="Total of Entry encoding"),
+ 'date':fields.datetime("Opening Date"),
+ 'closing_date':fields.datetime("Closing Date"),
+ 'starting_details_ids': fields.one2many('singer.statement', 'starting_id', string='Starting Details'),
+ 'ending_details_ids': fields.one2many('singer.statement', 'ending_id', string='Ending Details'),
+ 'name': fields.char('Name', size=64, required=True, readonly=True),
+
+ }
+ _defaults = {
+ 'state': lambda *a: 'draft',
+ 'name': lambda *a: '/',
+ 'date': lambda *a:time.strftime("%Y-%m-%d %H:%M:%S"),
+ 'journal_id': _default_journal_id,
+
+ }
+
+ def create(self, cr, uid, vals, context=None):
+ open_jrnl = self.search(cr, uid, [('company_id', '=', vals['company_id']), ('journal_id', '=', vals['journal_id']), ('state', '=', 'open')])
+ if open_jrnl:
+ raise osv.except_osv('Error', u'Une caisse de type espèce est déjà ouverte')
+ if 'starting_details_ids' in vals:
+ vals['starting_details_ids'] = starting_details_ids = map(list, vals['starting_details_ids'])
+ for i in starting_details_ids:
+ if i and i[0] and i[1]:
+ i[0], i[1] = 0, 0
+ res = super(account_bank_statement, self).create(cr, uid, vals, context=context)
+ return res
+
+ def onchange_journal_id(self, cursor, user, statement_id, journal_id, context=None):
+ id_s=[]
+ if not journal_id:
+ return {'value': {'balance_start': 0.0}}
+ balance_start=0.0
+ cash_obj = self.pool.get('singer.statement')
+ statement_obj = self.pool.get('account.bank.statement')
+ cursor.execute("Select a.id from account_bank_statement a where journal_id=%d and user_id=%d order by a.id desc limit 1"%(journal_id,user))
+ res2=cursor.fetchone()
+ res2=res2 and res2[0] or None
+ if res2:
+ statmt_id=statement_obj.browse(cursor,user,res2)
+ check_det=statmt_id.journal_id.check_dtls
+ if not check_det:
+ balance_start=statmt_id.balance_end_real or 0.0
+ return {'value': {'balance_start': balance_start}}
+ cursor.execute("Select a.id from account_bank_statement a, singer_statement s where journal_id=%d and user_id=%d order by a.id desc limit 1"%(journal_id,user))
+ res1=cursor.fetchone()
+ res1=res1 and res1[0] or None
+ if res1:
+ cursor.execute("Select sum(ss.pieces*ss.number),ss.ending_id from singer_statement ss, account_bank_statement s where ss.ending_id=s.id and s.journal_id=%d and s.user_id=%d and s.id=%d group by ss.ending_id,s.id order by s.id desc"%(journal_id,user, res1))
+ res = cursor.fetchone()
+ balance_start = res and res[0] or 0.0
+ cash_end=res and res[1] or None
+ id_s=statement_obj.browse(cursor,user,cash_end).ending_details_ids
+ new=[]
+ if id_s:
+ for s in id_s:
+ new.append(s.id)
+ return {'value': {'balance_start': balance_start, 'starting_details_ids':new}}
+
+ def button_open(self, cr, uid, ids, context=None):
+ obj_inv = self.browse(cr, uid, ids)[0]
+ s_id=obj_inv.journal_id
+ if s_id.statement_sequence_id:
+ s_id=s_id.id
+ number = self.pool.get('ir.sequence').get_id(cr, uid, s_id)
+ else:
+ number = self.pool.get('ir.sequence').get(cr, uid,
+ 'account.bank.statement')
+
+ self.write(cr, uid, ids, {'date':time.strftime("%Y-%m-%d %H:%M:%S"), 'state':'open', 'name':number})
+ return True
+
+ def button_confirm(self, cr, uid, ids, context=None):
+ val = 0.0
+ val2 = 0.0
+ val_statement_line = 0.0
+ diff = self.pool.get('res.users').browse(cr,uid,uid).company_id.max_diff or 0.0
+ for statement in self.browse(cr, uid, ids):
+ bal = statement.balance_end
+ bal_st=statement.balance_start
+ for st in statement.line_ids:
+ val_statement_line += st.amount
+ for stat in statement.starting_details_ids:
+ val2 += stat.subtotal
+ for stat in statement.ending_details_ids:
+ val += stat.subtotal
+ if statement.journal_id.check_dtls:
+ if Decimal(str(val)).quantize(Decimal('.001')) != (Decimal(str(val_statement_line)) + Decimal(str(val2))).quantize(Decimal('.001')):
+ raise osv.except_osv(_('Invalid action !'), _(' You can not confirm your cashbox, Please enter ending details, missing value matches to "%s"')%(abs(Decimal(str(val))-(Decimal(str(val_statement_line))+Decimal(str(val2))))))
+
+ self.write(cr, uid, statement.id, {'balance_end_real':Decimal(str(val_statement_line))+Decimal(str(val2)),'closing_date':time.strftime("%Y-%m-%d %H:%M:%S"),'state':'draft'})
+ # self.write(cr, uid, statement.id, {'balance_end_real':bal_st+val_statement_line,'closing_date':time.strftime("%Y-%m-%d %H:%M:%S"),'state':'draft'})
+ return super(account_bank_statement, self).button_confirm(cr, uid, ids, context=None)
+
+account_bank_statement()
+
+#class singer_account_bank_statement_line(osv.osv):
+# _inherit = 'account.bank.statement.line'
+# _columns = {
+# 'pos_statement_id': fields.many2one('pos.order',ondelete='cascade'),
+# }
+#
+#singer_account_bank_statement_line()
+
+
diff --git a/addons/point_of_sale/multi_company_demo.xml b/addons/point_of_sale/multi_company_demo.xml
new file mode 100644
index 00000000000..dfc59cc09c8
--- /dev/null
+++ b/addons/point_of_sale/multi_company_demo.xml
@@ -0,0 +1,38 @@
+
+
+
+
+ Tiny Editor
+
+
+
+ Tiny Editor
+
+
+ Free Business Solutions
+ Web: http://tiny.be - Tel: (+32).81.81.37.00 - Bank: CPH 126-2013269-07
+ IBAN: BE74 1262 0132 6907 - SWIFT: GKCCBEBB - VAT: BE0477.472.701
+
+
+
+
+
+ Tiny Integrator
+
+
+
+ Tiny Integrator
+
+
+ Free Business Solutions
+ Web: http://tiny.be - Tel: (+32).81.81.37.00 - Bank: CPH 126-2013269-07
+ IBAN: BE74 1262 0132 6907 - SWIFT: GKCCBEBB - VAT: BE0477.472.701
+
+
+
+
+
+
+
+
+
diff --git a/addons/point_of_sale/multi_company_stock_data.xml b/addons/point_of_sale/multi_company_stock_data.xml
new file mode 100644
index 00000000000..539a27ff1a2
--- /dev/null
+++ b/addons/point_of_sale/multi_company_stock_data.xml
@@ -0,0 +1,139 @@
+
+
+
+
+
+
+
+ property_product_pricelist
+
+
+
+
+
+
+
+ property_stock_account_output
+
+
+
+
+
+ property_stock_account_input
+
+
+
+
+
+ property_stock_account_output_categ
+
+
+
+
+
+ property_stock_account_input_categ
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/addons/point_of_sale/pos.py b/addons/point_of_sale/pos.py
index b26106477b1..e9c89570729 100644
--- a/addons/point_of_sale/pos.py
+++ b/addons/point_of_sale/pos.py
@@ -1,20 +1,21 @@
-# -*- coding: utf-8 -*-
+# -*- encoding: utf-8 -*-
##############################################################################
#
# OpenERP, Open Source Management Solution
-# Copyright (C) 2004-2010 Tiny SPRL ().
+# Copyright (C) 2004-2009 Tiny SPRL (). All Rights Reserved
+# $Id$
#
# 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.
+# it under the terms of the GNU 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.
+# GNU General Public License for more details.
#
-# You should have received a copy of the GNU Affero General Public License
+# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
#
##############################################################################
@@ -24,9 +25,9 @@ import netsvc
from osv import fields, osv
from mx import DateTime
from tools.translate import _
-import tools
-from wizard import except_wizard
from decimal import Decimal
+import tools
+import re
class pos_config_journal(osv.osv):
@@ -40,23 +41,53 @@ class pos_config_journal(osv.osv):
pos_config_journal()
+class res_mode_contact(osv.osv):
+ _name = "res.mode.contact"
+ _description = "Contact mode"
+ _columns={
+ 'name': fields.char('Mode', size=64, select=1),
+ 'active': fields.boolean('Active', select=2),
+ }
+res_mode_contact()
+
+class contact_mode_partner(osv.osv):
+ _inherit = 'res.partner'
+ _columns = {
+ 'contact_mode_id': fields.many2one('res.mode.contact','Contact Mode'),
+ }
+contact_mode_partner()
+
+
+class pos_company_discount(osv.osv):
+ _inherit = 'res.company'
+ _columns = {
+ 'company_discount': fields.float('Max Discount(%)', digits=(16,2)),
+ 'max_diff': fields.float('Max Difference for Cashboxes', digits=(16,2)),
+ 'account_receivable': fields.many2one('account.account',
+ 'Default Receivable', required=True, states={'draft': [('readonly', False)]}),
+ }
+
+pos_company_discount()
+
class pos_order(osv.osv):
_name = "pos.order"
_description = "Point of Sale"
_order = "date_order, create_date desc"
+ _order = "date_order desc"
def unlink(self, cr, uid, ids, context={}):
for rec in self.browse(cr, uid, ids, context=context):
- if rec.state != 'draft':
- raise osv.except_osv(_('Invalid action !'), _('Cannot delete a point of sale which is already confirmed !'))
+ for rec_statement in rec.statement_ids:
+ if (rec_statement.statement_id and rec_statement.statement_id.state=='confirm') or rec.state=='done':
+ raise osv.except_osv(_('Invalid action !'), _('Cannot delete a point of sale which is closed or contains confirmed cashboxes!'))
return super(pos_order, self).unlink(cr, uid, ids, context=context)
def onchange_partner_pricelist(self, cr, uid, ids, part, context={}):
if not part:
return {}
pricelist = self.pool.get('res.partner').browse(cr, uid, part).property_product_pricelist.id
- return {'value': {'pricelist_id': pricelist}}
+ return {'value':{'pricelist_id': pricelist}}
def _amount_total(self, cr, uid, ids, field_name, arg, context):
id_set = ",".join(map(str, ids))
@@ -68,39 +99,121 @@ class pos_order(osv.osv):
) AS amount
FROM pos_order p
LEFT OUTER JOIN pos_order_line l ON (p.id=l.order_id)
- WHERE p.id IN (""" + id_set +""") GROUP BY p.id """)
+ WHERE p.id IN (""" + id_set +""") GROUP BY p.id """)
res = dict(cr.fetchall())
-
for rec in self.browse(cr, uid, ids, context):
if rec.partner_id \
and rec.partner_id.property_account_position \
and rec.partner_id.property_account_position.tax_ids:
res[rec.id] = res[rec.id] - rec.amount_tax
+ else :
+ res[rec.id] = res[rec.id] + rec.amount_tax
return res
+ def _get_date_payment2(self, cr, uid, ids, context, *a):
+ res = {}
+ pay_obj = self.pool.get('account.bank.statement')
+ stat_obj_line = self.pool.get('account.bank.statement.line')
+ tot =0.0
+ val=None
+ for order in self.browse(cr, uid, ids):
+ cr.execute("select date_payment2 from pos_order where id=%d"%(order.id))
+ date_p=cr.fetchone()
+ date_p=date_p and date_p[0] or None
+ if date_p:
+ res[order.id]=date_p
+ return res
+ cr.execute(" SELECT max(l.date) from account_move_line l, account_move m, account_invoice i, account_move_reconcile r, pos_order o where i.move_id=m.id and l.move_id=m.id and l.reconcile_id=r.id and o.id=%d and o.invoice_id=i.id"%(order.id))
+ val=cr.fetchone()
+ val= val and val[0] or None
+ if not val:
+ cr.execute("select max(date) from account_bank_statement_line l, account_bank_statement_reconcile s where l.pos_statement_id=%d and l.reconcile_id=s.id"%(order.id))
+ val=cr.fetchone()
+ val=val and val[0] or None
+ if val:
+ res[order.id]=val
+ return res
+ def _get_date_payment(self, cr, uid, ids, context, *a):
+ res = {}
+ pay_obj = self.pool.get('pos.payment')
+ tot =0.0
+ val=None
+ for order in self.browse(cr, uid, ids):
+ cr.execute("select date_payment from pos_order where id=%d"%(order.id))
+ date_p=cr.fetchone()
+ date_p=date_p and date_p[0] or None
+ if date_p:
+ res[order.id]=date_p
+ return res
+ discount_allowed=order.company_id.company_discount
+ for line in order.lines:
+ if line.discount > discount_allowed:
+ return {order.id: None }
+ if order.amount_paid == order.amount_total and not date_p:
+ cr.execute("select max(date) from account_bank_statement_line where pos_statement_id=%d"%(order.id))
+ val=cr.fetchone()
+ val=val and val[0] or None
+ if order.invoice_id and order.invoice_id.move_id and not date_p and not val:
+ for o in order.invoice_id.move_id.line_id:
+ if o.balance==0:
+ if val %s"%(ids[0],comp))
+ res2=cr.fetchone()
+ cr.execute("select journal_id from account_bank_statement_line where pos_statement_id=%s "%(ids[0]))
+ res3=cr.fetchall()
+ list_jrnl=[]
+ for r in res3:
+ cr.execute("select id from account_journal where name= '%s' and special_journal='t'"%(r[0]))
+ res3=cr.fetchone()
+ is_special=res3 and res3[0] or None
+ if is_special:
+ list_jrnl.append(is_special)
+ r = {}
+ for order in self.browse(cr, uid, ids):
+ if order.state in ('paid','done','invoiced') and res and not res2 and not len(list_jrnl):
+ r[order.id] = 'accepted'
+ return r
+
_columns = {
'name': fields.char('Order Description', size=64, required=True,
states={'draft': [('readonly', False)]}, readonly=True),
+ 'company_id':fields.many2one('res.company', 'Company', required=True, readonly=True),
+ 'num_sale': fields.char('Internal Note', size=64),
'shop_id': fields.many2one('sale.shop', 'Shop', required=True,
states={'draft': [('readonly', False)]}, readonly=True),
'date_order': fields.datetime('Date Ordered', readonly=True),
+ 'date_payment': fields.function(_get_date_payment, method=True, string='Validation Date', type='date', store=True),
+ 'date_payment2': fields.function(_get_date_payment2, method=True, string='Payment Date', type='date', store=True),
'date_validity': fields.date('Validity Date', required=True),
- 'user_id': fields.many2one('res.users', 'Logged in User', readonly=True,
- help="This is the logged in user (not necessarily the salesman)."),
- 'salesman_id': fields.many2one('res.users', 'Salesman',
- help="This is the salesman actually making the order."),
+ 'user_id': fields.many2one('res.users', 'Connected Salesman', readonly=True),
+ 'user_id1': fields.many2one('res.users', 'Salesman', required=True),
+ 'user_id2': fields.many2one('res.users', 'Salesman Manager'),
'amount_tax': fields.function(_amount_tax, method=True, string='Taxes'),
'amount_total': fields.function(_amount_total, method=True, string='Total'),
- 'amount_paid': fields.function(_total_payment, 'Paid',
- states={'draft': [('readonly', False)]}, readonly=True,
- method=True),
+ 'amount_paid': fields.function(_total_payment, 'Paid', states={'draft': [('readonly', False)]}, readonly=True, method=True),
'amount_return': fields.function(_total_return, 'Returned', method=True),
- 'lines': fields.one2many('pos.order.line', 'order_id',
- 'Order Lines', states={'draft': [('readonly', False)]},
- readonly=True),
- 'payments': fields.one2many('pos.payment', 'order_id',
- 'Order Payments', states={'draft': [('readonly', False)]},
- readonly=True),
- 'pricelist_id': fields.many2one('product.pricelist', 'Pricelist',
- required=True, states={'draft': [('readonly', False)]},
- readonly=True),
- 'partner_id': fields.many2one(
- 'res.partner', 'Partner', change_default=True,
- states={'draft': [('readonly', False)], 'paid': [('readonly', False)]},
- readonly=True),
- 'state': fields.selection([('cancel', 'Cancel'), ('draft', 'Draft'),
- ('paid', 'Paid'), ('done', 'Done'), ('invoiced', 'Invoiced')], 'State',
- readonly=True,
- help=' * The \'Draft\' state is used when a user is encoding a new and unconfirmed pos order. \
- \n* The \'Paid\' state is set automatically when users makes payment for the pos order. \
- \n* The \'Invoiced\' state is set when invoice is created for pos order. \
- \n* The \'Done\' state is set automatically when user close the pos order.\
- \n* The \'Cancel\' state is used when user cancel pos order.'),
- 'invoice_id': fields.many2one('account.invoice', 'Invoice', readonly=True),
+ 'lines': fields.one2many('pos.order.line', 'order_id', 'Order Lines', states={'draft': [('readonly', False)]}, readonly=True),
+ 'price_type': fields.selection([
+ ('tax_excluded','Tax excluded')
+ ], 'Price method', required=True),
+ 'statement_ids': fields.one2many('account.bank.statement.line','pos_statement_id','Payments'),
+ 'payments': fields.one2many('pos.payment', 'order_id', 'Order Payments', states={'draft': [('readonly', False)]}, readonly=True),
+ 'pricelist_id': fields.many2one('product.pricelist', 'Pricelist', required=True, states={'draft': [('readonly', False)]}, readonly=True),
+ 'partner_id': fields.many2one( 'res.partner', 'Customer', change_default=True, select=1, states={'draft': [('readonly', False)], 'paid': [('readonly', False)]}),
+ 'state': fields.selection([('draft', 'Draft'), ('payment', 'Payment'),
+ ('advance','Advance'),
+ ('paid', 'Paid'), ('done', 'Done'), ('invoiced', 'Invoiced'), ('cancel', 'Cancel')],
+ 'State', readonly=True, ),
+ 'invoice_id': fields.many2one('account.invoice', 'Invoice'),
'account_move': fields.many2one('account.move', 'Account Entry', readonly=True),
'pickings': fields.one2many('stock.picking', 'pos_order', 'Picking', readonly=True),
- 'last_out_picking': fields.many2one('stock.picking',
- 'Last Output Picking',
- readonly=True),
- 'note': fields.text('Notes'),
+ 'last_out_picking': fields.many2one('stock.picking', 'Last Output Picking', readonly=True),
+ 'first_name': fields.char('First Name', size=64),
+ 'state_2': fields.function(_get_v,type='selection',selection=[('to_verify', 'To Verify'), ('accepted', 'Accepted'),
+ ('refused', 'Refused')], string='State', readonly=True, method=True, store=True),
+
+ # 'last_name': fields.char('Last Name', size=64),
+ # 'street': fields.char('Street', size=64),
+ # 'zip2': fields.char('Zip', size=64),
+ # 'city': fields.char('City', size=64),
+ # 'mobile': fields.char('Mobile', size=64),
+ # 'email': fields.char('Email', size=64),
+ 'note': fields.text('Internal Notes'),
'nb_print': fields.integer('Number of Print', readonly=True),
- 'sale_journal': fields.many2one('account.journal', 'Journal',
- required=True, states={'draft': [('readonly', False)]},
- readonly=True, ),
- 'account_receivable': fields.many2one('account.account',
- 'Default Receivable', required=True, states={'draft': [('readonly', False)]},
- readonly=True, ),
- 'invoice_wanted': fields.boolean('Create Invoice')
- }
+ 'sale_journal': fields.many2one('account.journal', 'Journal', required=True, states={'draft': [('readonly', False)]}, readonly=True, ),
+ # 'account_receivable': fields.many2one('account.account',
+ # 'Default Receivable', required=True, states={'draft': [('readonly', False)]},
+ # readonly=True, ),
+ 'invoice_wanted': fields.boolean('Create Invoice'),
+ 'note_2': fields.char('Customer Note',size=64),
+ 'type_rec': fields.char('Type of Receipt',size=64),
+ 'remboursed': fields.boolean('Remboursed'),
+ 'contract_number': fields.char('Contract Number', size=512, select=1),
+ 'journal_entry': fields.boolean('Journal Entry'),
+ }
+
+
+ def _select_pricelist(self, cr, uid, context):
+ pricelist = self.pool.get('product.pricelist').search(cr, uid, [('name', '=', 'Public Pricelist')])
+ if pricelist:
+ return pricelist[0]
+ else:
+ return False
def _journal_default(self, cr, uid, context={}):
journal_list = self.pool.get('account.journal').search(cr, uid, [('type', '=', 'cash')])
@@ -209,18 +370,22 @@ class pos_order(osv.osv):
_defaults = {
'user_id': lambda self, cr, uid, context: uid,
- 'salesman_id': lambda self, cr, uid, context: uid,
+ 'user_id2': lambda self, cr, uid, context: uid,
'state': lambda *a: 'draft',
- 'name': lambda obj, cr, uid, context: obj.pool.get('ir.sequence')\
- .get(cr, uid, 'pos.order'),
+ 'price_type': lambda *a: 'tax_excluded',
+ 'state_2': lambda *a: 'to_verify',
+ 'name': lambda obj, cr, uid, context: obj.pool.get('ir.sequence').get(cr, uid, 'pos.order'),
'date_order': lambda *a: time.strftime('%Y-%m-%d %H:%M:%S'),
'date_validity': lambda *a: (DateTime.now() + DateTime.RelativeDateTime(months=+6)).strftime('%Y-%m-%d'),
'nb_print': lambda *a: 0,
+ 'company_id': lambda self,cr,uid,c: self.pool.get('res.users').browse(cr, uid, uid, c).company_id.id,
'sale_journal': _sale_journal_get,
- 'account_receivable': _receivable_get,
- 'invoice_wanted': lambda *a: False
+ 'invoice_wanted': lambda *a: False,
+ 'shop_id': _shop_get,
+ 'pricelist_id': _select_pricelist,
}
+
def test_order_lines(self, cr, uid, order, context={}):
if not order.lines:
raise osv.except_osv(_('Error'), _('No order lines defined for this sale.'))
@@ -233,14 +398,11 @@ class pos_order(osv.osv):
return True
def test_paid(self, cr, uid, ids, context=None):
- def deci(val):
- return Decimal("%f" % (val, ))
-
for order in self.browse(cr, uid, ids, context):
if order.lines and not order.amount_total:
return True
- if (not order.lines) or (not order.payments) or \
- (deci(order.amount_paid) != deci(order.amount_total)):
+ if (not order.lines) or (not order.statement_ids) or \
+ Decimal(str(order.amount_total))!=Decimal(str(order.amount_paid)):
return False
return True
@@ -307,14 +469,11 @@ class pos_order(osv.osv):
def create_picking(self, cr, uid, ids, context={}):
"""Create a picking for each order and validate it."""
picking_obj = self.pool.get('stock.picking')
- partner_obj = self.pool.get('res.partner')
- address_id = False
+
orders = self.browse(cr, uid, ids, context)
for order in orders:
if not order.last_out_picking:
new = True
- if order.partner_id.id:
- address_id = partner_obj.address_get(cr, uid, [order.partner_id.id], ['delivery'])['delivery']
picking_id = picking_obj.create(cr, uid, {
'origin': order.name,
'type': 'out',
@@ -324,15 +483,11 @@ class pos_order(osv.osv):
'invoice_state': 'none',
'auto_picking': True,
'pos_order': order.id,
- 'address_id' : address_id
- },context)
+ })
self.write(cr, uid, [order.id], {'last_out_picking': picking_id})
else:
picking_id = order.last_out_picking.id
- picking_obj.write(cr, uid, [picking_id], {
- 'auto_picking': True,
- 'invoice_state': '2binvoiced',
- })
+ picking_obj.write(cr, uid, [picking_id], {'auto_picking': True})
picking = picking_obj.browse(cr, uid, [picking_id], context)[0]
new = False
@@ -343,14 +498,17 @@ class pos_order(osv.osv):
if new:
for line in order.lines:
- prop_ids = self.pool.get("ir.property").search(cr, uid,
- [('name', '=', 'property_stock_customer')])
- val = self.pool.get("ir.property").browse(cr, uid,
- prop_ids[0]).value
- location_id = order.shop_id.warehouse_id.lot_stock_id.id
+ if line.product_id and line.product_id.type=='service':
+ continue
+ prop_ids = self.pool.get("ir.property").search(cr, uid, [('name', '=', 'property_stock_customer')])
+ val = self.pool.get("ir.property").browse(cr, uid, prop_ids[0]).value
+ cr.execute("select s.id from stock_location s, stock_warehouse w where w.lot_stock_id=s.id and w.id= %d "%(order.shop_id.warehouse_id.id))
+ res=cr.fetchone()
+ location_id=res and res[0] or None
+# location_id = order and order.shop_id and order.shop_id.warehouse_id and order.shop_id.warehouse_id.lot_stock_id.id or None
stock_dest_id = int(val.split(',')[1])
if line.qty < 0:
- (location_id, stock_dest_id)= (stock_dest_id, location_id)
+ location_id, stock_dest_id = stock_dest_id, location_id
self.pool.get('stock.move').create(cr, uid, {
'name': 'Stock move (POS %d)' % (order.id, ),
@@ -361,17 +519,14 @@ class pos_order(osv.osv):
'product_uos_qty': abs(line.qty),
'product_qty': abs(line.qty),
'tracking_id': False,
- 'pos_line_id': line.id,
'state': 'waiting',
'location_id': location_id,
'location_dest_id': stock_dest_id,
})
wf_service = netsvc.LocalService("workflow")
- wf_service.trg_validate(uid, 'stock.picking',
- picking_id, 'button_confirm', cr)
- self.pool.get('stock.picking').force_assign(cr,
- uid, [picking_id], context)
+ wf_service.trg_validate(uid, 'stock.picking', picking_id, 'button_confirm', cr)
+ self.pool.get('stock.picking').force_assign(cr, uid, [picking_id], context)
return True
@@ -386,71 +541,92 @@ class pos_order(osv.osv):
wf_service.trg_create(uid, 'pos.order', i, cr)
return True
+ def button_invalidate(self, cr, uid, ids, *args):
+ res_obj = self.pool.get('res.company')
+ try:
+ part_company=res_obj.browse(cr,uid,uid) and res_obj.browse(cr,uid,uid).parent_id and res_obj.browse(cr,uid,uid).parent_id.id or None
+ except Exception, e:
+ raise osv.except_osv(_('Error'), _('You don\'t have enough access to validate this sale!'))
+ if part_company:
+ raise osv.except_osv(_('Error'), _('You don\'t have enough access to validate this sale!'))
+ return True
+
+ def button_validate(self, cr, uid, ids, *args):
+ res_obj = self.pool.get('res.company')
+ try:
+ part_company=res_obj.browse(cr,uid,uid) and res_obj.browse(cr,uid,uid).parent_id and res_obj.browse(cr,uid,uid).parent_id.id or None
+ except Exception, e:
+ raise osv.except_osv(_('Error'), _('You don\'t have enough access to validate this sale!'))
+ if part_company:
+ raise osv.except_osv(_('Error'), _('You don\'t have enough access to validate this sale!'))
+ for order in self.browse(cr, uid, ids):
+ if not order.date_payment:
+ cr.execute("select max(date) from account_bank_statement_line where pos_statement_id=%d"%(order.id))
+ val=cr.fetchone()
+ val=val and val[0] or None
+ if val:
+ cr.execute("Update pos_order set date_payment='%s' where id = %d"%(val, order.id))
+ cr.commit()
+ return True
+
+
def cancel_order(self, cr, uid, ids, context=None):
- """Cancel each picking with an inverted one."""
-
- picking_obj = self.pool.get('stock.picking')
- stock_move_obj = self.pool.get('stock.move')
- payment_obj = self.pool.get('pos.payment')
- picking_ids = picking_obj.search(cr, uid, [('pos_order', 'in', ids), ('state', '=', 'done')])
- clone_list = []
-
- # Copy all the picking and blank the last_out_picking
- for order in self.browse(cr, uid, ids, context=context):
- if not order.last_out_picking:
- continue
-
- clone_id = picking_obj.copy(
- cr, uid, order.last_out_picking.id, {'type': 'in'})
- # Confirm the picking
- wf_service = netsvc.LocalService("workflow")
- wf_service.trg_validate(uid, 'stock.picking',
- clone_id, 'button_confirm', cr)
- clone_list.append(clone_id)
- # Remove the ref to last picking and delete the payments
- self.write(cr, uid, ids, {'last_out_picking': False})
- payment_obj.unlink(cr, uid, [i.id for i in order.payments],
- context=context)
-
- # Switch all the moves
- move_ids = stock_move_obj.search(
- cr, uid, [('picking_id', '=', clone_id)])
- for move in stock_move_obj.browse(cr, uid, move_ids, context=context):
- stock_move_obj.write(
- cr, uid, move.id, {'location_id': move.location_dest_id.id,
- 'location_dest_id': move.location_id.id})
-
- self.pool.get('stock.picking').force_assign(cr,
- uid, clone_list, context)
-
+ self.write(cr, uid, ids, {'state': 'cancel'})
+ self.cancel_picking(cr, uid, ids, context={})
return True
def add_payment(self, cr, uid, order_id, data, context=None):
"""Create a new payment for the order"""
+ res_obj = self.pool.get('res.company')
+ statementl_obj = self.pool.get('account.bank.statement.line')
+ prod_obj = self.pool.get('product.product')
+ flag=''
+ curr_c=self.pool.get('res.users').browse(cr, uid, uid).company_id
+ curr_company=curr_c.id
order = self.browse(cr, uid, order_id, context)
+ if not order.num_sale and data['num_sale']:
+ self.write(cr,uid,order_id,{'num_sale': data['num_sale']})
+ ids_new=[]
if order.invoice_wanted and not order.partner_id:
raise osv.except_osv(_('Error'), _('Cannot create invoice without a partner.'))
-
args = {
- 'order_id': order_id,
- 'journal_id': data['journal'],
'amount': data['amount'],
- 'payment_id': data['payment_id'],
}
-
if 'payment_date' in data.keys():
- args['payment_date'] = data['payment_date']
+ args['date'] = data['payment_date']
if 'payment_name' in data.keys():
- args['payment_name'] = data['payment_name']
- if 'payment_nb' in data.keys():
- args['payment_nb'] = data['payment_nb']
+ args['name'] = data['payment_name'] + ' ' +order.name
+ account_def = self.pool.get('ir.property').get(cr, uid, 'property_account_receivable', 'res.partner', context=context)
+ args['account_id'] = order.partner_id and order.partner_id.property_account_receivable and order.partner_id.property_account_receivable.id or account_def or curr_c.account_receivable.id
+ if data.get('is_acc',False):
+ args['is_acc']=data['is_acc']
+ args['account_id']= prod_obj.browse(cr,uid, data['product_id']).property_account_income and prod_obj.browse(cr,uid, data['product_id']).property_account_income.id
+ if not args['account_id']:
+ raise osv.except_osv(_('Error'), _('Please provide an account for the product: %s')%(prod_obj.browse(cr,uid, data['product_id']).name))
+ args['partner_id'] = order.partner_id and order.partner_id.id or None
+ args['ref'] = order.contract_number or None
- payment_id = self.pool.get('pos.payment').create(cr, uid, args )
+ statement_obj= self.pool.get('account.bank.statement')
+ statement_id = statement_obj.search(cr,uid, [
+ ('journal_id', '=', data['journal']),
+ ('company_id', '=', curr_company),
+ ('user_id', '=', uid),
+ ('state', '=', 'open')])
+ if len(statement_id)==0:
+ raise osv.except_osv(_('Error !'), _('You have to open at least one cashbox'))
+ if statement_id:
+ statement_id=statement_id[0]
+ args['statement_id']= statement_id
+ args['pos_statement_id']= order_id
+ args['journal_id']= data['journal']
+ statement_line_id = self.pool.get('account.bank.statement.line').create(cr, uid, args)
+ ids_new.append(statement_id)
wf_service = netsvc.LocalService("workflow")
wf_service.trg_validate(uid, 'pos.order', order_id, 'paid', cr)
wf_service.trg_write(uid, 'pos.order', order_id, cr)
- return payment_id
+
+ return statement_id
def add_product(self, cr, uid, order_id, product_id, qty, context=None):
"""Create a new order line the order"""
@@ -486,26 +662,26 @@ class pos_order(osv.osv):
'note': 'REFUND\n'+ (order.note or ''),
'invoice_id': False,
'nb_print': 0,
- 'payments': False,
+ 'statement_ids': False,
})
clone_list.append(clone_id)
- self.write(cr, uid, clone_id, {
- 'partner_id': order.partner_id.id,
- })
+
for clone in self.browse(cr, uid, clone_list):
for order_line in clone.lines:
line_obj.write(cr, uid, [order_line.id], {
- 'qty': -order_line.qty,
+ 'qty': -order_line.qty
})
return clone_list
def action_invoice(self, cr, uid, ids, context={}):
+ res_obj = self.pool.get('res.company')
inv_ref = self.pool.get('account.invoice')
inv_line_ref = self.pool.get('account.invoice.line')
inv_ids = []
for order in self.browse(cr, uid, ids, context):
+ curr_c = order.user_id1.company_id
if order.invoice_id:
inv_ids.append(order.invoice_id.id)
continue
@@ -513,25 +689,26 @@ class pos_order(osv.osv):
if not order.partner_id:
raise osv.except_osv(_('Error'), _('Please provide a partner for the sale.'))
+ cr.execute('select a.id from account_account a, res_company p where p.account_receivable=a.id and p.id=%s', (curr_c.id, ))
+ res=cr.fetchone()
+ acc=res and res[0] or None
inv = {
'name': 'Invoice from POS: '+order.name,
'origin': order.name,
+ 'account_id':acc,
+ 'journal_id':order.sale_journal.id or None,
'type': 'out_invoice',
'reference': order.name,
'partner_id': order.partner_id.id,
'comment': order.note or '',
- 'price_type': 'tax_included'
}
inv.update(inv_ref.onchange_partner_id(cr, uid, [], 'out_invoice', order.partner_id.id)['value'])
-
- if not self.pool.get('res.partner').browse(cr, uid, inv['partner_id']).address:
- raise osv.except_osv(_('Error'), _('Unable to create invoice (partner has no address).'))
-
+ if not inv.get('account_id', None):
+ inv['account_id'] = acc
inv_id = inv_ref.create(cr, uid, inv, context)
self.write(cr, uid, [order.id], {'invoice_id': inv_id, 'state': 'invoiced'})
inv_ids.append(inv_id)
-
for line in order.lines:
inv_line = {
'invoice_id': inv_id,
@@ -539,11 +716,12 @@ class pos_order(osv.osv):
'quantity': line.qty,
}
inv_line.update(inv_line_ref.product_id_change(cr, uid, [],
- line.product_id.id,
- line.product_id.uom_id.id,
- line.qty, partner_id = order.partner_id.id, fposition_id=order.partner_id.property_account_position.id)['value'])
+ line.product_id.id,
+ line.product_id.uom_id.id,
+ line.qty, partner_id = order.partner_id.id, fposition_id=order.partner_id.property_account_position.id)['value'])
inv_line['price_unit'] = line.price_unit
inv_line['discount'] = line.discount
+ inv_line['account_id'] = acc
inv_line['invoice_line_tax_id'] = ('invoice_line_tax_id' in inv_line)\
and [(6, 0, inv_line['invoice_line_tax_id'])] or []
@@ -555,8 +733,6 @@ class pos_order(osv.osv):
return inv_ids
def create_account_move(self, cr, uid, ids, context=None):
- if context is None:
- context = {}
account_move_obj = self.pool.get('account.move')
account_move_line_obj = self.pool.get('account.move.line')
account_period_obj = self.pool.get('account.period')
@@ -564,14 +740,13 @@ class pos_order(osv.osv):
period = account_period_obj.find(cr, uid, context=context)[0]
for order in self.browse(cr, uid, ids, context=context):
-
+ curr_c = self.pool.get('res.users').browse(cr, uid, uid).company_id
+ comp_id = self.pool.get('res.users').browse(cr, order.user_id.id, order.user_id.id).company_id
+ comp_id=comp_id and comp_id.id or False
to_reconcile = []
group_tax = {}
-
- if order.amount_total > 0:
- order_account = order.sale_journal.default_credit_account_id.id
- else:
- order_account = order.sale_journal.default_debit_account_id.id
+ account_def = self.pool.get('ir.property').get(cr, uid, 'property_account_receivable', 'res.partner', context=context)
+ order_account = order.partner_id and order.partner_id.property_account_receivable and order.partner_id.property_account_receivable.id or account_def or curr_c.account_receivable.id
# Create an entry for the sale
move_id = account_move_obj.create(cr, uid, {
@@ -584,8 +759,12 @@ class pos_order(osv.osv):
tax_amount = 0
taxes = [t for t in line.product_id.taxes_id]
- computed_taxes = account_tax_obj.compute_inv(
- cr, uid, taxes, line.price_unit, line.qty)
+ if order.price_type=='tax_excluded':
+ computed_taxes = account_tax_obj.compute(
+ cr, uid, taxes, line.price_unit, line.qty)
+ else:
+ computed_taxes = account_tax_obj.compute_inv(
+ cr, uid, taxes, line.price_unit, line.qty)
for tax in computed_taxes:
tax_amount += round(tax['amount'], 2)
@@ -597,8 +776,10 @@ class pos_order(osv.osv):
group_tax[group_key] += round(tax['amount'], 2)
else:
group_tax[group_key] = round(tax['amount'], 2)
-
- amount = line.price_subtotal - tax_amount
+ if order.price_type!='tax_excluded':
+ amount = line.price_subtotal - tax_amount
+ else:
+ amount = line.price_subtotal
# Search for the income account
if line.product_id.property_account_income.id:
@@ -631,18 +812,20 @@ class pos_order(osv.osv):
# Create a move for the line
account_move_line_obj.create(cr, uid, {
- 'name': order.name,
+ 'name': "aa"+order.name,
'date': order.date_order,
- 'ref': order.name,
+ 'ref': order.contract_number or order.name,
+ 'quantity': line.qty,
+ 'product_id':line.product_id.id,
'move_id': move_id,
'account_id': income_account,
+ 'company_id': comp_id,
'credit': ((amount>0) and amount) or 0.0,
'debit': ((amount<0) and -amount) or 0.0,
'journal_id': order.sale_journal.id,
'period_id': period,
'tax_code_id': tax_code_id,
'tax_amount': tax_amount,
- 'partner_id' : order.partner_id and order.partner_id.id or False,
}, context=context)
# For each remaining tax with a code, whe create a move line
@@ -657,18 +840,20 @@ class pos_order(osv.osv):
continue
account_move_line_obj.create(cr, uid, {
- 'name': order.name,
+ 'name': "bb"+order.name,
'date': order.date_order,
- 'ref': order.name,
+ 'ref': order.contract_number or order.name,
+ 'product_id':line.product_id.id,
+ 'quantity': line.qty,
'move_id': move_id,
'account_id': income_account,
+ 'company_id': comp_id,
'credit': 0.0,
'debit': 0.0,
'journal_id': order.sale_journal.id,
'period_id': period,
'tax_code_id': tax_code_id,
'tax_amount': tax_amount,
- 'partner_id' : order.partner_id and order.partner_id.id or False,
}, context=context)
@@ -676,10 +861,13 @@ class pos_order(osv.osv):
(tax_code_pos, base_code_pos, account_pos)= (0, 1, 2)
for key, amount in group_tax.items():
account_move_line_obj.create(cr, uid, {
- 'name': order.name,
+ 'name':"cc"+order.name,
'date': order.date_order,
- 'ref': order.name,
+ 'ref': order.contract_number or order.name,
'move_id': move_id,
+ 'company_id': comp_id,
+ 'quantity': line.qty,
+ 'product_id':line.product_id.id,
'account_id': key[account_pos],
'credit': ((amount>0) and amount) or 0.0,
'debit': ((amount<0) and -amount) or 0.0,
@@ -687,15 +875,15 @@ class pos_order(osv.osv):
'period_id': period,
'tax_code_id': key[tax_code_pos],
'tax_amount': amount,
- 'partner_id' : order.partner_id and order.partner_id.id or False,
}, context=context)
# counterpart
to_reconcile.append(account_move_line_obj.create(cr, uid, {
- 'name': order.name,
+ 'name': "dd"+order.name,
'date': order.date_order,
- 'ref': order.name,
+ 'ref': order.contract_number or order.name,
'move_id': move_id,
+ 'company_id': comp_id,
'account_id': order_account,
'credit': ((order.amount_total<0) and -order.amount_total)\
or 0.0,
@@ -703,7 +891,6 @@ class pos_order(osv.osv):
or 0.0,
'journal_id': order.sale_journal.id,
'period_id': period,
- 'partner_id' : order.partner_id and order.partner_id.id or False,
}, context=context))
@@ -713,94 +900,157 @@ class pos_order(osv.osv):
raise osv.except_osv(_('Error !'),
_('There is no receivable account defined for this journal:'\
' "%s" (id:%d)') % (order.sale_journal.name, order.sale_journal.id, ))
+ am=0.0
+ for payment in order.statement_ids:
+ am+=payment.amount
- for payment in order.payments:
- if not payment.journal_id.default_debit_account_id:
- raise osv.except_osv(_('No Default Debit Account !'),
- _('You have to define a Default Debit Account for your Financial Journals!\n'))
-
- if not payment.journal_id.default_credit_account_id:
- raise osv.except_osv(_('No Default Credit Account !'),
- _('You have to define a Default Credit Account for your Financial Journals!\n'))
-
- if payment.amount > 0:
- payment_account = payment.journal_id.default_debit_account_id.id
+ if am > 0:
+ payment_account = \
+ payment.statement_id.journal_id.default_debit_account_id.id
else:
- payment_account = payment.journal_id.default_credit_account_id.id
-
- if payment.amount > 0:
- order_account = \
- order.sale_journal.default_credit_account_id.id
- else:
- order_account = \
- order.sale_journal.default_debit_account_id.id
+ payment_account = \
+ payment.statement_id.journal_id.default_credit_account_id.id
# Create one entry for the payment
+ if payment.is_acc:
+ continue
payment_move_id = account_move_obj.create(cr, uid, {
- 'journal_id': payment.journal_id.id,
+ 'journal_id': payment.statement_id.journal_id.id,
'period_id': period,
}, context=context)
- account_move_line_obj.create(cr, uid, {
- 'name': order.name,
- 'date': order.date_order,
- 'ref': order.name,
- 'move_id': payment_move_id,
- 'account_id': payment_account,
- 'credit': ((payment.amount<0) and -payment.amount) or 0.0,
- 'debit': ((payment.amount>0) and payment.amount) or 0.0,
- 'journal_id': payment.journal_id.id,
- 'period_id': period,
- 'partner_id' : order.partner_id and order.partner_id.id or False,
- }, context=context)
- to_reconcile.append(account_move_line_obj.create(cr, uid, {
- 'name': order.name,
- 'date': order.date_order,
- 'ref': order.name,
- 'move_id': payment_move_id,
- 'account_id': order_account,
- 'credit': ((payment.amount>0) and payment.amount) or 0.0,
- 'debit': ((payment.amount<0) and -payment.amount) or 0.0,
- 'journal_id': payment.journal_id.id,
- 'period_id': period,
- 'partner_id' : order.partner_id and order.partner_id.id or False,
- }, context=context))
- account_move_obj.button_validate(cr, uid, [move_id, payment_move_id], context=context)
- account_move_line_obj.reconcile(cr, uid, to_reconcile, type='manual', context=context)
+ for stat_l in order.statement_ids:
+ if stat_l.is_acc and len(stat_l.move_ids):
+ for st in stat_l.move_ids:
+ for s in st.line_id:
+ if s.credit:
+ account_move_line_obj.copy(cr, uid, s.id, { 'debit': s.credit,
+ 'statement_id': False,
+ 'credit': s.debit})
+ account_move_line_obj.copy(cr, uid, s.id, {
+ 'statement_id': False,
+ 'account_id':order_account
+ })
+ # account_move_obj.button_validate(cr, uid, [move_id, payment_move_id], context=context)
+ self.write(cr,uid,order.id,{'state':'done'})
+ # account_move_line_obj.reconcile(cr, uid, to_reconcile, type='manual', context=context)
return True
+ def cancel_picking(self, cr, uid, ids, context=None):
+ for order in self.browse(cr, uid, ids, context=context):
+ for picking in order.pickings:
+ self.pool.get('stock.picking').unlink(cr, uid, [picking.id], context)
+ return True
+
+
+ def action_payment(self, cr, uid, ids, context=None):
+ vals = {'state': 'payment'}
+ for pos in self.browse(cr, uid, ids):
+ create_contract_nb = False
+ for line in pos.lines:
+ if line.product_id.product_type == 'MD':
+ create_contract_nb = True
+ break
+ if create_contract_nb:
+ seq = self.pool.get('ir.sequence').get(cr, uid, 'pos.user_%s' % pos.user_id1.login)
+ vals['contract_number'] ='%s-%s' % (pos.user_id1.login, seq)
+ self.write(cr, uid, ids, vals)
+
def action_paid(self, cr, uid, ids, context=None):
- if context is None:
+ if not context:
context = {}
- self.create_picking(cr, uid, ids, context=context)
- self.write(cr, uid, ids, {'state': 'paid'})
+ if context.get('flag',False):
+ self.create_picking(cr, uid, ids, context={})
+ self.write(cr, uid, ids, {'state': 'paid'})
+ else:
+ context['flag']=True
return True
def action_cancel(self, cr, uid, ids, context=None):
- if context is None:
- context = {}
- self.cancel_order(cr, uid, ids, context=context)
self.write(cr, uid, ids, {'state': 'cancel'})
return True
def action_done(self, cr, uid, ids, context=None):
- if context is None:
- context = {}
- self.create_account_move(cr, uid, ids, context=context)
- self.write(cr, uid, ids, {'state': 'done'})
+ for order in self.browse(cr, uid, ids, context=context):
+ if not order.journal_entry:
+ self.create_account_move(cr, uid, ids, context={})
+ #self.write(cr, uid, ids, {'state': 'done'})
return True
+ def compute_state(self, cr, uid, id):
+ cr.execute("select act.id, act.name from wkf_activity act "
+ "inner join wkf_workitem item on act.id=item.act_id "
+ "inner join wkf_instance inst on item.inst_id=inst.id "
+ "inner join wkf on inst.wkf_id=wkf.id "
+ "where wkf.osv='pos.order' and inst.res_id=%s "
+ "order by act.name", (id,))
+ return [name for id, name in cr.fetchall()]
+
pos_order()
+class account_bank_statement(osv.osv):
+ _inherit = 'account.bank.statement'
+ _columns={
+ 'user_id': fields.many2one('res.users',ondelete='cascade',string='User', readonly=True),
+ }
+ _defaults = {
+ 'user_id': lambda self,cr,uid,c: self.pool.get('res.users').browse(cr, uid, uid, c).id
+ }
+account_bank_statement()
+
+class account_bank_statement_line(osv.osv):
+ _inherit = 'account.bank.statement.line'
+ def _get_statement_journal(self, cr, uid, ids, context, *a):
+ res = {}
+ for line in self.browse(cr, uid, ids):
+ res[line.id] = line.statement_id and line.statement_id.journal_id and line.statement_id.journal_id.name or None
+ return res
+ _columns={
+ 'journal_id': fields.function(_get_statement_journal, method=True,store=True, string='Journal', type='char', size=64),
+ 'am_out':fields.boolean("To count"),
+ 'is_acc':fields.boolean("Is accompte"),
+ 'pos_statement_id': fields.many2one('pos.order',ondelete='cascade'),
+ }
+account_bank_statement_line()
class pos_order_line(osv.osv):
_name = "pos.order.line"
_description = "Lines of Point of Sale"
- def _amount_line(self, cr, uid, ids, field_name, arg, context):
+ def _get_amount(self, cr, uid, ids, field_name, arg, context):
res = {}
for line in self.browse(cr, uid, ids):
- res[line.id] = line.price_unit * line.qty * (1 - (line.discount or 0.0) / 100.0)
+ price = self.price_by_product(cr, uid, ids, line.order_id.pricelist_id.id, line.product_id.id, line.qty, line.order_id.partner_id.id)
+ res[line.id]=price
+ return res
+
+ def _amount_line_ttc(self, cr, uid, ids, field_name, arg, context):
+ res = {}
+ account_tax_obj = self.pool.get('account.tax')
+ for line in self.browse(cr, uid, ids):
+ tax_amount = 0.0
+ taxes = [t for t in line.product_id.taxes_id]
+ computed_taxes = account_tax_obj.compute(cr, uid, taxes, line.price_unit, line.qty)
+ for tax in computed_taxes:
+ tax_amount += tax['amount']
+ price = self.price_by_product(cr, uid, ids, line.order_id.pricelist_id.id, line.product_id.id, line.qty, line.order_id.partner_id.id)
+ if line.discount!=0.0:
+ res[line.id] = line.price_unit * line.qty * (1 - (line.discount or 0.0) / 100.0)
+ else:
+ res[line.id]=line.price_unit*line.qty
+ res[line.id] = res[line.id] + tax_amount
+
+ return res
+ def _amount_line(self, cr, uid, ids, field_name, arg, context):
+ res = {}
+
+ for line in self.browse(cr, uid, ids):
+ price = self.price_by_product(cr, uid, ids, line.order_id.pricelist_id.id, line.product_id.id, line.qty, line.order_id.partner_id.id)
+ if line.discount!=0.0:
+ res[line.id] = line.price_unit * line.qty * (1 - (line.discount or 0.0) / 100.0)
+# res[line.id] = price * line.qty * (1 - (line.discount or 0.0) / 100.0)
+ else:
+ res[line.id]=line.price_unit*line.qty
return res
def price_by_product(self, cr, uid, ids, pricelist, product_id, qty=0, partner_id=False):
@@ -810,9 +1060,9 @@ class pos_order_line(osv.osv):
raise osv.except_osv(_('No Pricelist !'),
_('You have to select a pricelist in the sale form !\n' \
'Please set one before choosing a product.'))
-
+ p_obj = self.pool.get('product.product').browse(cr,uid,product_id).list_price
price = self.pool.get('product.pricelist').price_get(cr, uid,
- [pricelist], product_id, qty or 1.0, partner_id)[pricelist]
+ [pricelist], product_id, qty or 1.0, partner_id)[pricelist]
if price is False:
raise osv.except_osv(_('No valid pricelist line found !'),
_("Couldn't find a pricelist line matching this product" \
@@ -822,17 +1072,66 @@ class pos_order_line(osv.osv):
def onchange_product_id(self, cr, uid, ids, pricelist, product_id, qty=0, partner_id=False):
price = self.price_by_product(cr, uid, ids, pricelist, product_id, qty, partner_id)
+ self.write(cr,uid,ids,{'price_unit':price})
+ return {'value': {'price_unit': price}, 'qty': 1}
- return {'value': {'price_unit': price}}
+ def onchange_subtotal(self, cr, uid, ids, discount, price, pricelist,qty,partner_id, product_id,*a):
+ prod_obj = self.pool.get('product.product')
+ price_f = self.price_by_product(cr, uid, ids, pricelist, product_id, qty, partner_id)
+ prod_id=''
+ if product_id:
+ prod_id=prod_obj.browse(cr,uid,product_id).disc_controle
+ disc=0.0
+ if (disc != 0.0 or prod_id) and price_f>0:
+ disc=100-(price/price_f*100)
+ return {'value':{'discount':disc, 'price_unit':price_f}}#,'notice':''}}#, 'price_subtotal':(price_f*qty*(1-disc))}}
+ return {}
+ def onchange_ded(self, cr, uid,ids, val_ded,price_u,*a):
+ pos_order = self.pool.get('pos.order.line')
+ res_obj = self.pool.get('res.users')
+ res_company = self.pool.get('res.company')
+ comp = res_obj.browse(cr,uid,uid).company_id.company_discount or 0.0
+ val=0.0
+ if val_ded and price_u:
+ val=100.0*val_ded/price_u
+ if val > comp:
+ return {'value': {'discount':val, 'notice':'' }}
+ return {'value': {'discount':val}}
+
+ def onchange_discount(self, cr, uid,ids, discount,price,*a):
+ pos_order = self.pool.get('pos.order.line')
+ res_obj = self.pool.get('res.users')
+ res_company = self.pool.get('res.company')
+ company_disc = pos_order.browse(cr,uid,ids)
+ if discount:
+ if not company_disc:
+ comp=res_obj.browse(cr,uid,uid).company_id.company_discount or 0.0
+ else:
+ comp= company_disc[0] and company_disc[0].order_id.company_id and company_disc[0].order_id.company_id.company_discount or 0.0
+
+ if discount > comp :
+ return {'value': {'notice':'','price_ded':price*discount*0.01 or 0.0 }}
+ else:
+ return {'value': {'notice':'Minimum Discount','price_ded':price*discount*0.01 or 0.0 }}
+ else :
+ return {'value': {'notice':'No Discount', 'price_ded':price*discount*0.01 or 0.0 }}
_columns = {
'name': fields.char('Line Description', size=512),
+ 'company_id':fields.many2one('res.company', 'Company', required=True),
+ 'notice': fields.char('Discount Notice', size=128, required=True),
+ 'serial_number': fields.char('Serial Number', size=128),
+# 'contract_number': fields.char('Contract Number', size=512),
'product_id': fields.many2one('product.product', 'Product', domain=[('sale_ok', '=', True)], required=True, change_default=True),
- 'price_unit': fields.float('Unit Price', required=True),
+# 'price_unit': fields.float('Unit Price'),
+ 'price_unit': fields.function(_get_amount, method=True, string='Unit Price', store=True),
+ 'price_ded': fields.float('Discount(Amount)'),
'qty': fields.float('Quantity'),
- 'price_subtotal': fields.function(_amount_line, method=True, string='Subtotal'),
+ 'qty_rfd': fields.float('Refunded Quantity'),
+ 'price_subtotal': fields.function(_amount_line, method=True, string='Subtotal w/o Tax'),
+ 'price_subtotal_incl': fields.function(_amount_line_ttc, method=True, string='Subtotal'),
'discount': fields.float('Discount (%)', digits=(16, 2)),
- 'order_id': fields.many2one('pos.order', 'Order Reference', ondelete='cascade'),
+ 'order_id': fields.many2one('pos.order', 'Order Ref', ondelete='cascade'),
'create_date': fields.datetime('Creation Date', readonly=True),
}
@@ -840,6 +1139,9 @@ class pos_order_line(osv.osv):
'name': lambda obj, cr, uid, context: obj.pool.get('ir.sequence').get(cr, uid, 'pos.order.line'),
'qty': lambda *a: 1,
'discount': lambda *a: 0.0,
+ 'price_ded': lambda *a: 0.0,
+ 'notice': lambda *a: 'No Discount',
+ 'company_id': lambda self,cr,uid,c: self.pool.get('res.users').browse(cr, uid, uid, c).company_id.id,
}
def create(self, cr, user, vals, context={}):
@@ -862,7 +1164,7 @@ class pos_order_line(osv.osv):
product_id = self.pool.get('product.product').search(cr, uid, [('ean13','=', ean)])
if not product_id:
- return False
+ return False
# search price product
product = self.pool.get('product.product').read(cr, uid, product_id)
@@ -884,7 +1186,7 @@ class pos_order_line(osv.osv):
}
line_id = self.create(cr, uid, vals)
if not line_id:
- raise except_wizard(_('Error'), _('Create line failed !'))
+ raise wizard.except_wizard(_('Error'), _('Create line failed !'))
else:
vals = {
'qty': qty,
@@ -892,19 +1194,12 @@ class pos_order_line(osv.osv):
}
line_id = self.write(cr, uid, order_line_id, vals)
if not line_id:
- raise except_wizard(_('Error'), _('Modify line failed !'))
+ raise wizard.except_wizard(_('Error'), _('Modify line failed !'))
line_id = order_line_id
price_line = float(qty)*float(price)
return {'name': product_name, 'product_id': product_id[0], 'price': price, 'price_line': price_line ,'qty': qty }
- def unlink(self, cr, uid, ids, context={}):
- """Allows to delete pos order lines in draft,cancel state"""
- for rec in self.browse(cr, uid, ids, context=context):
- if rec.order_id.state not in ['draft','cancel']:
- raise osv.except_osv(_('Invalid action !'), _('Cannot delete an order line which is %s !')%(rec.order_id.state,))
- return super(pos_order_line, self).unlink(cr, uid, ids, context=context)
-
pos_order_line()
@@ -928,7 +1223,7 @@ class pos_payment(osv.osv):
_columns = {
'name': fields.char('Description', size=64),
- 'order_id': fields.many2one('pos.order', 'Order Reference', required=True, ondelete='cascade'),
+ 'order_id': fields.many2one('pos.order', 'Order Ref', required=True, ondelete='cascade'),
'journal_id': fields.many2one('account.journal', "Journal", required=True),
'payment_id': fields.many2one('account.payment.term','Payment Term', select=True),
'payment_nb': fields.char('Piece Number', size=32),
@@ -963,33 +1258,266 @@ class report_transaction_pos(osv.osv):
_auto = False
_columns = {
'date_create': fields.char('Date', size=16, readonly=True),
- 'journal_id': fields.many2one('account.journal', 'Journal', readonly=True),
+ 'journal_id': fields.many2one('account.journal', 'Sales Journal', readonly=True),
+ 'jl_id': fields.many2one('account.journal', 'Cash Journals', readonly=True),
'user_id': fields.many2one('res.users', 'User', readonly=True),
'no_trans': fields.float('Number of Transaction', readonly=True),
'amount': fields.float('Amount', readonly=True),
- 'invoice_id': fields.many2one('account.invoice', 'Invoice', readonly=True),
+ 'invoice_id': fields.float('Nbr Invoice', readonly=True),
+ 'invoice_am': fields.float('Invoice Amount', readonly=True),
+ 'product_nb': fields.float('Product Nb.', readonly=True),
+ 'disc': fields.float('Disc.', readonly=True),
}
def init(self, cr):
tools.drop_view_if_exists(cr, 'report_transaction_pos')
cr.execute("""
create or replace view report_transaction_pos as (
- select
- min(pp.id) as id,
- count(pp.id) as no_trans,
- sum(amount) as amount,
- pp.journal_id,
- to_char(pp.create_date, 'YYYY-MM-DD') as date_create,
- ps.user_id,
- ps.invoice_id
+ select
+ min(absl.id) as id,
+ count(absl.id) as no_trans,
+ sum(absl.amount) as amount,
+ sum(line.price_ded) as disc,
+ to_char(date_trunc('day',absl.create_date),'YYYY-MM-DD')::text as date_create,
+ po.user_id as user_id,
+ po.sale_journal as journal_id,
+ abs.journal_id as jl_id,
+ count(po.invoice_id) as invoice_id,
+ count(p.id) as product_nb
from
- pos_payment pp, pos_order ps
- WHERE ps.id = pp.order_id
+ account_bank_statement_line as absl,
+ account_bank_statement as abs,
+ product_product as p,
+ pos_order_line as line,
+ pos_order as po
+ where
+ absl.pos_statement_id = po.id and
+ line.order_id=po.id and
+ line.product_id=p.id and
+ absl.statement_id=abs.id
+
group by
- pp.journal_id, date_create, ps.user_id, ps.invoice_id
- )
- """)
+ po.user_id,po.sale_journal, abs.journal_id,
+ to_char(date_trunc('day',absl.create_date),'YYYY-MM-DD')::text
+ )
+ """)
+ #to_char(date_trunc('day',absl.create_date),'YYYY-MM-DD')
+ #to_char(date_trunc('day',absl.create_date),'YYYY-MM-DD')::text as date_create,
report_transaction_pos()
-# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
+class report_sales_by_user_pos(osv.osv):
+ _name = "report.sales.by.user.pos"
+ _description = "Sales by user"
+ _auto = False
+ _columns = {
+ 'date_order': fields.date('Order Date',required=True, select=True),
+ 'amount': fields.float('Total', readonly=True, select=True),
+ 'qty': fields.float('Quantity', readonly=True, select=True),
+ 'user_id': fields.many2one('res.users', 'User', readonly=True, select=True),
+ }
+ def init(self, cr):
+ tools.drop_view_if_exists(cr, 'report_sales_by_user_pos')
+ cr.execute("""
+ create or replace view report_sales_by_user_pos as (
+ select
+ min(po.id) as id,
+ to_char(date_trunc('day',po.date_order),'YYYY-MM-DD')::text as date_order,
+ po.user_id as user_id,
+ sum(pol.qty)as qty,
+ sum((pol.price_unit * pol.qty * (1 - (pol.discount) / 100.0))) as amount
+ from
+ pos_order as po,pos_order_line as pol,product_product as pp,product_template as pt
+ where
+ pt.id=pp.product_tmpl_id and pp.id=pol.product_id and po.id = pol.order_id
+ group by
+ to_char(date_trunc('day',po.date_order),'YYYY-MM-DD')::text,
+ po.user_id
+
+ )
+ """)
+report_sales_by_user_pos()
+
+class report_sales_by_user_pos_month(osv.osv):
+ _name = "report.sales.by.user.pos.month"
+ _description = "Sales by user monthly"
+ _auto = False
+ _columns = {
+ 'date_order': fields.date('Order Date',required=True, select=True),
+ 'amount': fields.float('Total', readonly=True, select=True),
+ 'qty': fields.float('Quantity', readonly=True, select=True),
+ 'user_id': fields.many2one('res.users', 'User', readonly=True, select=True),
+ }
+
+ def init(self, cr):
+ tools.drop_view_if_exists(cr, 'report_sales_by_user_pos_month')
+ cr.execute("""
+ create or replace view report_sales_by_user_pos_month as (
+ select
+ min(po.id) as id,
+ to_char(date_trunc('month',po.date_order),'YYYY-MM-DD')::text as date_order,
+ po.user_id as user_id,
+ sum(pol.qty)as qty,
+ sum((pol.price_unit * pol.qty * (1 - (pol.discount) / 100.0))) as amount
+ from
+ pos_order as po,pos_order_line as pol,product_product as pp,product_template as pt
+ where
+ pt.id=pp.product_tmpl_id and pp.id=pol.product_id and po.id = pol.order_id
+ group by
+ to_char(date_trunc('month',po.date_order),'YYYY-MM-DD')::text,
+ po.user_id
+
+ )
+ """)
+report_sales_by_user_pos_month()
+
+class report_sales_by_margin_pos(osv.osv):
+ _name = "report.sales.by.margin.pos"
+ _description = "Sales by margin"
+ _auto = False
+ _columns = {
+# 'pos_name': fields.char('POS Order', size=64, readonly=True),
+ 'product_name':fields.char('Product Name', size=64, readonly=True),
+ 'date_order': fields.date('Order Date',required=True, select=True),
+ 'amount': fields.float('Total', readonly=True, select=True),
+ 'user_id': fields.many2one('res.users', 'User', readonly=True, select=True),
+ 'qty': fields.float('Qty', readonly=True, select=True),
+ 'net_margin_per_qty':fields.float('Net margin per Qty', readonly=True, select=True),
+ 'total':fields.float('Margin', readonly=True, select=True),
+
+ }
+
+ def init(self, cr):
+ tools.drop_view_if_exists(cr, 'report_sales_by_margin_pos')
+ cr.execute("""
+ create or replace view report_sales_by_margin_pos as (
+ select
+ min(pol.id) as id,
+ po.user_id as user_id,
+ pt.name as product_name,
+ to_char(date_trunc('day',po.date_order),'YYYY-MM-DD')::text as date_order,
+ sum(pol.qty) as qty,
+ pt.list_price-pt.standard_price as net_margin_per_qty,
+ (pt.list_price-pt.standard_price) *sum(pol.qty) as total
+ from
+ product_template as pt,
+ product_product as pp,
+ pos_order_line as pol,
+ pos_order as po
+ where
+ pol.product_id = pp.product_tmpl_id and
+ pp.product_tmpl_id = pt.id and
+ po.id = pol.order_id
+
+ group by
+ pt.name,
+ pt.list_price,
+ pt.standard_price,
+ po.user_id,
+ to_char(date_trunc('day',po.date_order),'YYYY-MM-DD')::text
+
+ )
+ """)
+report_sales_by_margin_pos()
+
+class report_sales_by_margin_pos_month(osv.osv):
+ _name = "report.sales.by.margin.pos.month"
+ _description = "Sales by margin monthly"
+ _auto = False
+ _columns = {
+# 'pos_name': fields.char('POS Order', size=64, readonly=True),
+ 'product_name':fields.char('Product Name', size=64, readonly=True),
+ 'date_order': fields.date('Order Date',required=True, select=True),
+ 'amount': fields.float('Total', readonly=True, select=True),
+ 'user_id': fields.many2one('res.users', 'User', readonly=True, select=True),
+ 'qty': fields.float('Qty', readonly=True, select=True),
+ 'net_margin_per_qty':fields.float('Net margin per Qty', readonly=True, select=True),
+ 'total':fields.float('Margin', readonly=True, select=True),
+
+ }
+
+ def init(self, cr):
+ tools.drop_view_if_exists(cr, 'report_sales_by_margin_pos_month')
+ cr.execute("""
+ create or replace view report_sales_by_margin_pos_month as (
+ select
+ min(pol.id) as id,
+ po.user_id as user_id,
+ pt.name as product_name,
+ to_char(date_trunc('month',po.date_order),'YYYY-MM-DD')::text as date_order,
+ sum(pol.qty) as qty,
+ pt.list_price-pt.standard_price as net_margin_per_qty,
+ (pt.list_price-pt.standard_price) *sum(pol.qty) as total
+ from
+ product_template as pt,
+ product_product as pp,
+ pos_order_line as pol,
+ pos_order as po
+ where
+ pol.product_id = pp.product_tmpl_id and
+ pp.product_tmpl_id = pt.id and
+ po.id = pol.order_id
+
+ group by
+ pt.name,
+ pt.list_price,
+ pt.standard_price,
+ po.user_id,
+ to_char(date_trunc('month',po.date_order),'YYYY-MM-DD')::text
+
+ )
+ """)
+report_sales_by_margin_pos_month()
+
+
+class account_move_line(osv.osv):
+ _inherit = 'account.move.line'
+ def create(self, cr, user, vals, context={}):
+ pos_obj = self.pool.get('pos.order')
+ val_name = vals.get('name', '')
+ val_ref = vals.get('ref', '')
+ if (val_name and 'POS' in val_name) and (val_ref and 'PACK' in val_ref):
+ aaa = re.search(r'Stock move.\((.*)\)', vals.get('name'))
+ name_pos = aaa.groups()[0]
+ pos_id = name_pos.replace('POS ','')
+ if pos_id and pos_id.isdigit():
+ pos_curr = pos_obj.browse(cr,user,int(pos_id))
+ pos_curr = pos_curr and pos_curr.contract_number or ''
+ vals['ref'] = pos_curr or vals.get('ref')
+ return super(account_move_line, self).create(cr, user, vals, context)
+
+account_move_line()
+
+
+class account_move(osv.osv):
+ _inherit = 'account.move'
+ def create(self, cr, user, vals, context={}):
+ pos_obj = self.pool.get('pos.order')
+ val_name = vals.get('name', '')
+ val_ref = vals.get('ref', '')
+ if (val_name and 'POS' in val_name) and (val_ref and 'PACK' in val_ref):
+ aaa = re.search(r'Stock move.\((.*)\)', vals.get('name'))
+ name_pos = aaa.groups()[0]
+ pos_id = name_pos.replace('POS ','')
+ if pos_id and pos_id.isdigit():
+ pos_curr = pos_obj.browse(cr,user,int(pos_id))
+ pos_curr = pos_curr and pos_curr.contract_number or ''
+ vals['ref'] = pos_curr or vals.get('ref')
+ return super(account_move, self).create(cr, user, vals, context)
+
+account_move()
+
+
+class product_product(osv.osv):
+ _inherit = 'product.product'
+ _columns = {
+ 'income_pdt': fields.boolean('Product for Incoming'),
+ 'expense_pdt': fields.boolean('Product for expenses'),
+ 'am_out': fields.boolean('Controle for Outgoing Operations'),
+ 'disc_controle': fields.boolean('Discount Controle '),
+}
+ _defaults = {
+ 'disc_controle': lambda *a: True,
+}
+product_product()
+# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
diff --git a/addons/point_of_sale/pos_account_bank_statement.py b/addons/point_of_sale/pos_account_bank_statement.py
new file mode 100644
index 00000000000..887a7b8060c
--- /dev/null
+++ b/addons/point_of_sale/pos_account_bank_statement.py
@@ -0,0 +1,54 @@
+# -*- encoding: utf-8 -*-
+##############################################################################
+#
+# OpenERP, Open Source Management Solution
+# Copyright (C) 2004-2009 Tiny SPRL (). All Rights Reserved
+# $Id$
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU 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 General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
+#
+##############################################################################
+
+from osv import osv, fields
+import time
+import netsvc
+
+
+class account_bank_statement(osv.osv):
+ _inherit = 'account.bank.statement'
+ _columns = {
+ 'company_id':fields.many2one('res.company', 'Company', required=True),
+ }
+ _defaults = {
+ 'company_id': lambda self,cr,uid,c: self.pool.get('res.users').browse(cr, uid, uid, c).company_id.id,
+ }
+account_bank_statement()
+
+class account_bank_statement_line(osv.osv):
+ def _default_company(self, cr, uid, context={}):
+ user = self.pool.get('res.users').browse(cr, uid, uid, context=context)
+ if user.company_id:
+ return user.company_id.id
+ return self.pool.get('res.company').search(cr, uid, [('parent_id', '=', False)])[0]
+ _inherit = 'account.bank.statement.line'
+ _columns = {
+ 'company_id':fields.many2one('res.company', 'Company', required=True),
+ }
+ _defaults = {
+ 'company_id': lambda self,cr,uid,c: self.pool.get('res.users').browse(cr, uid, uid, c).company_id.id,
+ }
+account_bank_statement_line()
+
+# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
+
diff --git a/addons/point_of_sale/pos_data.xml b/addons/point_of_sale/pos_data.xml
index 5e562bc2ad7..8ff4697804e 100644
--- a/addons/point_of_sale/pos_data.xml
+++ b/addons/point_of_sale/pos_data.xml
@@ -1,32 +1,60 @@
-
+
+
+ Paiement
+
+
+ Acompte
+
+ service
+ 0.0
+ 0.0
+
+
+
+
-
+
+ Reparation
+
+ service
+ 100.0
+ 100.0
+
+
+
+
-
-
-
-
-
-
-
-
-
-
+
+ Bon
+
-
+
+ GIFT
+ produce
+ 1.0
+ 1.0
+
+
+ 0.0
+ Cheque cadeau
+
+
-
-
-
-
+
+ PORT01
+ produce
+ 1.0
+ 1.0
+
+
+ 0.0
+ Shipping cost
+
+ service
+ 0
+
+
+
diff --git a/addons/point_of_sale/pos_demo.xml b/addons/point_of_sale/pos_demo.xml
new file mode 100644
index 00000000000..789d96b897d
--- /dev/null
+++ b/addons/point_of_sale/pos_demo.xml
@@ -0,0 +1,205 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Main Receivable
+ x 40000
+ receivable
+
+
+
+
+
+
+
+This chart of account is used for automated testing purpose. It is installed
+only if you selected demo data during your database creation. Modules can
+do black box testing on entries on this chart of account, without modifying
+your own chart of account.
+
+
+
+
+
diff --git a/addons/point_of_sale/pos_report.xml b/addons/point_of_sale/pos_report.xml
index c9956c2c029..2e9ff5e6107 100644
--- a/addons/point_of_sale/pos_report.xml
+++ b/addons/point_of_sale/pos_report.xml
@@ -1,53 +1,145 @@
-
-
+
+
-
-
+
-
+
-
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/addons/point_of_sale/pos_view.xml b/addons/point_of_sale/pos_view.xml
index 3f328f00f4d..f0afcd1aac1 100644
--- a/addons/point_of_sale/pos_view.xml
+++ b/addons/point_of_sale/pos_view.xml
@@ -1,6 +1,7 @@
+
pos.orderpos.order
@@ -9,103 +10,125 @@
+
+
+
+
+
+
diff --git a/addons/point_of_sale/report/all_closed_cashbox_of_the_day.py b/addons/point_of_sale/report/all_closed_cashbox_of_the_day.py
new file mode 100644
index 00000000000..854acfde3a9
--- /dev/null
+++ b/addons/point_of_sale/report/all_closed_cashbox_of_the_day.py
@@ -0,0 +1,141 @@
+# -*- encoding: utf-8 -*-
+##############################################################################
+#
+# OpenERP, Open Source Management Solution
+# Copyright (C) 2004-2009 Tiny SPRL (). All Rights Reserved
+# $Id$
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU 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 General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
+#
+##############################################################################
+import time
+from report import report_sxw
+
+
+class all_closed_cashbox_of_the_day(report_sxw.rml_parse):
+
+ def __init__(self, cr, uid, name, context):
+ super(all_closed_cashbox_of_the_day, self).__init__(cr, uid, name, context)
+ self.localcontext.update({
+ 'time': time,
+ 'get_data':self._get_data,
+ 'get_bal':self._get_bal,
+ 'get_lines':self._get_lines,
+ 'get_partner':self._get_partner,
+ 'get_net_total':self._get_net_total,
+ 'get_user':self._get_user,
+ 'get_sub_total':self._get_sub_total,
+ 'get_net_total_starting':self._get_net_total_starting,
+ })
+ def _get_user(self,line_ids):
+ sql = "select name from res_users where id = %d"%(line_ids['create_uid'])
+ self.cr.execute(sql)
+ user = self.cr.fetchone()
+ return user[0]
+
+ def _get_data(self,user):
+ data = {}
+ sql = """ SELECT abs.journal_id,abs.id,abs.date,abs.closing_date,abs.name as statement,aj.name as journal,ap.name as period,ru.name as user,rc.name as company,
+ abs.state,abs.balance_end_real FROM account_bank_statement as abs
+ LEFT JOIN account_journal as aj ON aj.id = abs.journal_id
+ LEFT JOIN account_period as ap ON ap.id = abs.period_id
+ LEFT JOIN res_users as ru ON ru.id = abs.user_id
+ LEFT JOIN res_company as rc ON rc.id = abs.company_id
+ WHERE to_char(date_trunc('day',abs.date),'YYYY-MM-DD')::date = current_date and abs.state in ('confirm','open') and abs.user_id = %d"""%(user.id)
+ self.cr.execute(sql)
+ data = self.cr.dictfetchall()
+ return data
+
+ def _get_lines(self,statement):
+ data = {}
+ sql = """ select absl.* from account_bank_statement_line as absl, account_bank_statement as abs
+ where absl.statement_id = abs.id and abs.id = %d"""%(statement['id'])
+ self.cr.execute(sql)
+ data = self.cr.dictfetchall()
+ return data
+
+ def _get_bal(self,data):
+ res = {}
+ sql =""" select sum(pieces*number) as bal from singer_statement where starting_id = %d """%(data['id'])
+ self.cr.execute(sql)
+ res = self.cr.dictfetchall()
+ if res :
+ return res[0]['bal']
+ else :
+ return False
+
+ def _get_sub_total(self,user,data,date):
+ res={}
+ self.cr.execute(""" select sum(absl.amount) from account_bank_statement as abs
+ LEFT JOIN account_bank_statement_line as absl ON abs.id = absl.statement_id
+ WHERE abs.journal_id = %d
+ and abs.state in ('confirm','open')
+ and abs.date = '%s'
+ and abs.user_id = %d
+ """%(data,date,user.id))
+ res = self.cr.fetchall()
+ if res[0][0]:
+ return res[0][0]
+ else:
+ return False
+ def _get_partner(self,statement):
+ res = {}
+ sql =""" select rp.name from account_bank_statement_line as absl,res_partner as rp
+ where absl.partner_id = rp.id
+ and absl.pos_statement_id = %d"""%(statement['pos_statement_id'])
+ self.cr.execute(sql)
+ res = self.cr.dictfetchall()
+ if res :
+ return res[0]['name']
+ else :
+ return 0.00
+
+
+ def _get_net_total_starting(self,user):
+ lst = []
+ res={}
+ total_ending_bal = 0.0
+ total_starting_bal = 0.0
+ sql = """ SELECT abs.id,abs.balance_end_real as net_total FROM account_bank_statement as abs
+ WHERE to_char(date_trunc('day',abs.date),'YYYY-MM-DD')::date = current_date
+ and abs.state in ('confirm','open')
+ and abs.user_id = %d"""%(user.id)
+ self.cr.execute(sql)
+ res = self.cr.dictfetchall()
+ for r in res :
+ total_ending_bal += (r['net_total'] or 0.0)
+ sql1 =""" select sum(pieces*number) as bal from singer_statement where starting_id = %d"""%(r['id'])
+ self.cr.execute(sql1)
+ data = self.cr.dictfetchall()
+ if data[0]['bal']:
+ total_starting_bal += data[0]['bal']
+ lst.append(total_ending_bal)
+ lst.append(total_starting_bal)
+ return lst
+
+ def _get_net_total(self,user):
+ lst = []
+ res={}
+ total_ending_bal = 0.0
+ total_starting_bal = 0.0
+ sql = """select sum(absl.amount) as net_total from account_bank_statement as abs
+ LEFT JOIN account_bank_statement_line as absl ON abs.id = absl.statement_id
+ where abs.state in ('confirm','open') and abs.user_id = %d
+ and to_char(date_trunc('day',abs.date),'YYYY-MM-DD')::date = current_date """%(user.id)
+
+ self.cr.execute(sql)
+ res = self.cr.dictfetchall()
+ return res[0]['net_total'] or 0.0
+
+report_sxw.report_sxw('report.all.closed.cashbox.of.the.day', 'account.bank.statement', 'addons/statement/report/all_closed_cashbox_of_the_day.rml', parser=all_closed_cashbox_of_the_day)
diff --git a/addons/point_of_sale/report/all_closed_cashbox_of_the_day.rml b/addons/point_of_sale/report/all_closed_cashbox_of_the_day.rml
new file mode 100644
index 00000000000..63bae7c798f
--- /dev/null
+++ b/addons/point_of_sale/report/all_closed_cashbox_of_the_day.rml
@@ -0,0 +1,299 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/addons/point_of_sale/report/pos_details_summary.py b/addons/point_of_sale/report/pos_details_summary.py
index 9ac04d70235..826844effd6 100644
--- a/addons/point_of_sale/report/pos_details_summary.py
+++ b/addons/point_of_sale/report/pos_details_summary.py
@@ -1,21 +1,22 @@
-# -*- coding: utf-8 -*-
+# -*- encoding: utf-8 -*-
##############################################################################
-#
-# OpenERP, Open Source Management Solution
-# Copyright (C) 2004-2010 Tiny SPRL ().
+#
+# OpenERP, Open Source Management Solution
+# Copyright (C) 2004-2009 Tiny SPRL (). All Rights Reserved
+# $Id$
#
# 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.
+# it under the terms of the GNU 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.
+# GNU 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 .
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
#
##############################################################################
@@ -108,7 +109,7 @@ class pos_details_summary(report_sxw.rml_parse):
return '%s - %s' % (min_date, max_date)
def __init__(self, cr, uid, name, context):
- super(pos_details_summary, self).__init__(cr, uid, name, context=context)
+ super(pos_details_summary, self).__init__(cr, uid, name, context)
self.total = 0.0
self.localcontext.update({
'time': time,
diff --git a/addons/point_of_sale/report/pos_details_summary.rml b/addons/point_of_sale/report/pos_details_summary.rml
index 50f70778ab1..254f397b6b6 100644
--- a/addons/point_of_sale/report/pos_details_summary.rml
+++ b/addons/point_of_sale/report/pos_details_summary.rml
@@ -6,6 +6,48 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -51,6 +93,13 @@
+
+
+
+
+
+
+
@@ -77,35 +126,59 @@
-
- Detail of Sales
-
-
-
-
-
- Company: [[ company.name ]]
-
-
- Print Date: [[time.strftime('%Y-%m-%d')]]
-
-
- Period: [[ '%s' % getperiod(objects) ]]
-
-
+
-
-
+
+
-
-
-
-
-
+
+ Detail of Sales
+
+
+
+
+
+
+ Company
+
+
+ Print Date
+
+
+ Period
+
+
+
+
+
+
+ [[ company.name ]]
+
+
+ [[time.strftime('%Y-%m-%d')]]
+
+
+ [[ '%s' % getperiod(objects) ]]
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
Mode of Taxes
@@ -115,12 +188,12 @@
[[ p[0] ]]
[[ '%.2f' % (p[1],) ]]
-
-
-
+
+
+
-
+
Mode of payment
@@ -131,40 +204,48 @@
[[ '%.2f' % (p[1],) ]]
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Summary
+
-
Summary
+
Sales total
+ terp_tblheader_Details
+
[[ '%d' % getsalestotal(objects) ]]
-
Sales total
-
[[ '%d' % getsalestotal(objects) ]]
+
Qty of product
+
[[ '%d' % getqtytotal(objects) ]]
-
Qty of product
-
[[ '%d' % getqtytotal(objects) ]]
+
Total invoiced
+
[[ '%.2f' % getsuminvoice(objects) ]]
-
Total invoiced
-
[[ '%.2f' % getsuminvoice(objects) ]]
+
Total discount
+
[[ '%.2f' % getsumdisc(objects) ]]
-
Total discount
-
[[ '%.2f' % getsumdisc(objects) ]]
+
Total paid
+
[[ '%.2f' % getpaidtotal(objects) ]]
-
Total paid
-
[[ '%.2f' % getpaidtotal(objects) ]]
-
-
-
Total of the day
-
[[ '%.2f' % gettotalofthaday(objects) ]]
+
Total of the day
+
[[ '%.2f' % gettotalofthaday(objects) ]]
-
-
-
+
diff --git a/addons/point_of_sale/report/pos_invoice.py b/addons/point_of_sale/report/pos_invoice.py
index cddfc678c84..d9f345ca185 100644
--- a/addons/point_of_sale/report/pos_invoice.py
+++ b/addons/point_of_sale/report/pos_invoice.py
@@ -1,21 +1,22 @@
-# -*- coding: utf-8 -*-
+# -*- encoding: utf-8 -*-
##############################################################################
-#
+#
# OpenERP, Open Source Management Solution
-# Copyright (C) 2004-2010 Tiny SPRL ().
+# Copyright (C) 2004-2009 Tiny SPRL (). All Rights Reserved
+# $Id$
#
# 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.
+# it under the terms of the GNU 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.
+# GNU 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 .
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
#
##############################################################################
@@ -28,10 +29,11 @@ from tools.translate import _
class pos_invoice(report_sxw.rml_parse):
def __init__(self, cr, uid, name, context):
- super(pos_invoice, self).__init__(cr, uid, name, context=context)
+ super(pos_invoice, self).__init__(cr, uid, name, context)
self.localcontext.update({
'time': time,
})
+ print
def set_context(self, objects, data, ids, report_type=None):
super(pos_invoice, self).set_context(objects, data, ids, report_type)
diff --git a/addons/point_of_sale/report/pos_lines.py b/addons/point_of_sale/report/pos_lines.py
index 753b5821af6..1abec66dc80 100644
--- a/addons/point_of_sale/report/pos_lines.py
+++ b/addons/point_of_sale/report/pos_lines.py
@@ -1,21 +1,22 @@
-# -*- coding: utf-8 -*-
+# -*- encoding: utf-8 -*-
##############################################################################
-#
+#
# OpenERP, Open Source Management Solution
-# Copyright (C) 2004-2010 Tiny SPRL ().
+# Copyright (C) 2004-2009 Tiny SPRL (). All Rights Reserved
+# $Id$
#
# 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.
+# it under the terms of the GNU 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.
+# GNU 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 .
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
#
##############################################################################
@@ -26,7 +27,7 @@ from report import report_sxw
class pos_lines(report_sxw.rml_parse):
def __init__(self, cr, uid, name, context):
- super(pos_lines, self).__init__(cr, uid, name, context=context)
+ super(pos_lines, self).__init__(cr, uid, name, context)
self.total = 0.0
self.localcontext.update({
'time': time,
diff --git a/addons/point_of_sale/report/pos_payment_report.py b/addons/point_of_sale/report/pos_payment_report.py
new file mode 100644
index 00000000000..f27add1e208
--- /dev/null
+++ b/addons/point_of_sale/report/pos_payment_report.py
@@ -0,0 +1,79 @@
+# -*- encoding: utf-8 -*-
+##############################################################################
+#
+# OpenERP, Open Source Management Solution
+# Copyright (C) 2004-2009 Tiny SPRL (). All Rights Reserved
+# $Id$
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU 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 General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
+#
+##############################################################################
+import time
+from report import report_sxw
+
+
+class pos_payment_report(report_sxw.rml_parse):
+
+ def __init__(self, cr, uid, name, context):
+ super(pos_payment_report, self).__init__(cr, uid, name, context)
+ self.total = 0.0
+ self.localcontext.update({
+ 'time': time,
+ 'pos_payment': self._pos_payment,
+ 'pos_payment_total':self._pos_payment_total,
+ })
+
+ def _pos_payment(self,obj):
+ data={}
+ sql = """ select id from pos_order where id = %d"""%(obj.id)
+ self.cr.execute(sql)
+ if self.cr.fetchone():
+ self.cr.execute ("select pt.name,pol.qty,pol.discount,pol.price_unit, " \
+ "(pol.price_unit * pol.qty * (1 - (pol.discount) / 100.0)) as total " \
+ "from pos_order as po,pos_order_line as pol,product_product as pp,product_template as pt " \
+ "where pt.id=pp.product_tmpl_id and pp.id=pol.product_id and po.id = pol.order_id " \
+ "and po.state in ('paid','invoiced') and to_char(date_trunc('day',po.date_order),'YYYY-MM-DD')::date = current_date and po.id=%d"%(obj.id))
+ data=self.cr.dictfetchall()
+ else :
+ self.cr.execute ("select pt.name,pol.qty,pol.discount,pol.price_unit, " \
+ "(pol.price_unit * pol.qty * (1 - (pol.discount) / 100.0)) as total " \
+ "from pos_order as po,pos_order_line as pol,product_product as pp,product_template as pt " \
+ "where pt.id=pp.product_tmpl_id and pp.id=pol.product_id and po.id = pol.order_id " \
+ "and po.state in ('paid','invoiced') and to_char(date_trunc('day',po.date_order),'YYYY-MM-DD')::date = current_date")
+ data=self.cr.dictfetchall()
+ print data
+ for d in data:
+ self.total += d['price_unit'] * d['qty']
+ return data
+
+
+ def _pos_payment_total(self,o):
+# res=[]
+# self.cr.execute ("select sum(pol.price_unit * pol.qty * (1 - (pol.discount) / 100.0)) " \
+# "from pos_order as po,pos_order_line as pol,product_product as pp,product_template as pt " \
+# "where pt.id=pp.product_tmpl_id and pp.id=pol.product_id and po.id = pol.order_id " \
+# "and po.state='paid' and po.date_order = current_date and po.id=%d"%(o.id))
+# res=self.cr.fetchone()[0]
+ return self.total
+
+
+report_sxw.report_sxw('report.pos.payment.report', 'pos.order', 'addons/point_of_sale/report/pos_payment_report.rml', parser=pos_payment_report)
+
+
+
+
+
+
+
+
diff --git a/addons/point_of_sale/report/pos_payment_report.rml b/addons/point_of_sale/report/pos_payment_report.rml
new file mode 100644
index 00000000000..ebe30bdf3bc
--- /dev/null
+++ b/addons/point_of_sale/report/pos_payment_report.rml
@@ -0,0 +1,216 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ [[ formatLang(pos_payment_user_total(data['form'])) or removeParentNode('blockTable')]]
+
+
+
+
+
+
+
diff --git a/addons/point_of_sale/report/pos_receipt.py b/addons/point_of_sale/report/pos_receipt.py
index e21bf514b6d..fbceae7ebf4 100644
--- a/addons/point_of_sale/report/pos_receipt.py
+++ b/addons/point_of_sale/report/pos_receipt.py
@@ -1,51 +1,53 @@
-# -*- coding: utf-8 -*-
+# -*- encoding: utf-8 -*-
##############################################################################
-#
+#
# OpenERP, Open Source Management Solution
-# Copyright (C) 2004-2010 Tiny SPRL ().
+# Copyright (C) 2004-2009 Tiny SPRL (). All Rights Reserved
+# $Id$
#
# 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.
+# it under the terms of the GNU 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.
+# GNU 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 .
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
#
##############################################################################
import time
from report import report_sxw
-from mx.DateTime.ISO import ParseAny
import pooler
+def titlize(journal_name):
+ res = []
+ words = journal_name.split()
+ while words.pop() != 'journal':
+ continue
+ return ' '.join(words)
class order(report_sxw.rml_parse):
def __init__(self, cr, uid, name, context):
- super(order, self).__init__(cr, uid, name, context=context)
+ super(order, self).__init__(cr, uid, name, context)
user = pooler.get_pool(cr.dbname).get('res.users').browse(cr, uid, uid)
partner = user.company_id.partner_id
self.localcontext.update({
'time': time,
- 'dformat': '%Y/%m/%d %H:%M:%S',
'disc': self.discount,
'net': self.netamount,
- 'formatdate': self.formatdate,
+ 'get_journal_amt': self._get_journal_amt,
'address': partner.address and partner.address[0] or False,
+ 'titlize': titlize
})
- def formatdate(self, datestr):
- dateobj = ParseAny(datestr)
- return dateobj.strftime(self.localcontext['dformat'])
-
def netamount(self, order_line_id):
sql = 'select (qty*price_unit) as net_price from pos_order_line where id = %s'
self.cr.execute(sql, (order_line_id,))
@@ -62,6 +64,16 @@ class order(report_sxw.rml_parse):
dsum = dsum +(line[2] * (line[0]*line[1]/100))
return dsum
+ def _get_journal_amt(self, order_id):
+ data={}
+ sql = """ select aj.name,absl.amount as amt from account_bank_statement as abs
+ LEFT JOIN account_bank_statement_line as absl ON abs.id = absl.statement_id
+ LEFT JOIN account_journal as aj ON aj.id = abs.journal_id
+ WHERE absl.pos_statement_id =%d"""%(order_id)
+ self.cr.execute(sql)
+ data = self.cr.dictfetchall()
+ return data
+
report_sxw.report_sxw('report.pos.receipt', 'pos.order', 'addons/point_of_sale/report/pos_receipt.rml', parser=order, header=False)
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
diff --git a/addons/point_of_sale/report/pos_receipt.rml b/addons/point_of_sale/report/pos_receipt.rml
index 6dd8df26924..ecf1aa8c52a 100644
--- a/addons/point_of_sale/report/pos_receipt.rml
+++ b/addons/point_of_sale/report/pos_receipt.rml
@@ -1,185 +1,197 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- [[ repeatIn(objects,'o') ]]
- [[ setLang(o.user_id.context_lang) ]]
- [[o.user_id.company_id.name]]
- [[ address and address.street ]], [[ address and address.zip ]] [[ address and address.city ]]
- Tel : [[ address and address.phone ]]
- Fax : [[ address and address.fax ]]
- E-mail : [[ address and address.email ]]
-
-
-
-
-
-
- OPERATION N° : [[ o.name ]]
- Date : [[ formatdate(o.date_order) ]]
-
-
-
-
-
-
- Description
-
-
- Qty
-
-
- Price
-
-
-
-
- [[ repeatIn(o.lines,'line') ]]
-
-
-
- [[ len(line.product_id.name) > 39 and line.product_id.name[:39] + '...' or line.product_id.name ]]
-
-
- [[ '%.f' % line.qty ]]
-
-
- [[ '%.2f' % net(line.id) ]]
-
-
-
-
-
-
-
-
-
-
- Discount :
-
-
- [[ not(disc(o.id)) and removeParentNode('blockTable') or disc(o.id) ]] [[ o.pricelist_id.currency_id.name ]]
-
[[ repeatIn(o.lines,'line') ]]
+ [[ len(line.product_id.name) > 39 and line.product_id.name[:39] + '...' or line.product_id.name ]]
+
+
+
+ [[o.state=='cancel' and o.statement_ids and '-' or '']][['%.f' % line.qty ]]
+
+
+
+ [[o.state=='cancel' and o.statement_ids and '-' or '']][[ '%.2f' % net(line.id) ]] [[ line and line.discount == 0.0 and removeParentNode('font') ]] ([[ '%.2f' % line.discount ]]%)
+
+
+
+
+
+
+ Taxes :
+
+
+ [[o.state=='cancel' and o.statement_ids and '-' or '']][['%.2f' % o.amount_tax ]]
+
+
+
+
+
+
+
+
+ Total :
+
+
+ [[o.state=='cancel' and o.statement_ids and '-' or '']][['%.2f' % o.amount_total ]]
+
+
+
+
+
+
+
diff --git a/addons/point_of_sale/report/pos_receipt_with_remboursment.py b/addons/point_of_sale/report/pos_receipt_with_remboursment.py
new file mode 100644
index 00000000000..539f2d1548d
--- /dev/null
+++ b/addons/point_of_sale/report/pos_receipt_with_remboursment.py
@@ -0,0 +1,80 @@
+# -*- encoding: utf-8 -*-
+##############################################################################
+#
+# OpenERP, Open Source Management Solution
+# Copyright (C) 2004-2009 Tiny SPRL (). All Rights Reserved
+# $Id$
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU 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 General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
+#
+##############################################################################
+
+import time
+from report import report_sxw
+import pooler
+
+
+class order(report_sxw.rml_parse):
+
+ def __init__(self, cr, uid, name, context):
+ super(order, self).__init__(cr, uid, name, context)
+
+ user = pooler.get_pool(cr.dbname).get('res.users').browse(cr, uid, uid)
+ partner = user.company_id.partner_id
+
+ self.localcontext.update({
+ 'time': time,
+ 'disc': self.discount,
+ 'net': self.netamount,
+ 'get_journal_amt': self._get_journal_amt,
+ 'address': partner.address and partner.address[0] or False,
+ })
+
+ def netamount(self, order_line_id):
+ sql = 'select (qty*price_unit) as net_price from pos_order_line where id = %s'
+ self.cr.execute(sql, (order_line_id,))
+ res = self.cr.fetchone()
+ return res[0]
+
+ def discount(self, order_id):
+ sql = 'select discount, price_unit, qty from pos_order_line where order_id = %s '
+ self.cr.execute(sql, (order_id,))
+ res = self.cr.fetchall()
+ dsum = 0
+ for line in res:
+ if line[0] != 0:
+ dsum = dsum +(line[2] * (line[0]*line[1]/100))
+ return dsum
+ def _get_journal_amt(self, order_id):
+ lst=[]
+ sql = """ select aj.name from account_bank_statement as abs
+ LEFT JOIN account_bank_statement_line as absl ON abs.id = absl.statement_id
+ LEFT JOIN account_journal as aj ON aj.id = abs.journal_id
+ WHERE absl.pos_statement_id = %d"""%(order_id.id)
+ self.cr.execute(sql)
+ res = self.cr.fetchone()
+ lst.append(res[0])
+ sql2 = """ select sum(absl.amount) as amt from account_bank_statement as abs
+ LEFT JOIN account_bank_statement_line as absl ON abs.id = absl.statement_id
+ LEFT JOIN account_journal as aj ON aj.id = abs.journal_id
+ where aj.name = '%s' """%(res[0])
+ self.cr.execute(sql2)
+ res1 = self.cr.fetchone()
+ lst.append(res1[0])
+ return lst
+
+report_sxw.report_sxw('report.pos.receipt.with.remboursment', 'pos.order', 'addons/point_of_sale/report/pos_receipt_with_remboursment.rml', parser=order, header=False)
+
+# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
+
diff --git a/addons/point_of_sale/report/pos_receipt_with_remboursment.rml b/addons/point_of_sale/report/pos_receipt_with_remboursment.rml
new file mode 100644
index 00000000000..01fa0e4ac1e
--- /dev/null
+++ b/addons/point_of_sale/report/pos_receipt_with_remboursment.rml
@@ -0,0 +1,131 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ [[ repeatIn(objects,'o') ]]
+ [[ repeatIn(objects,'o') ]]
+ [[o.user_id.company_id.name]]
+ [[ address and address.street ]], [[ address and address.zip ]] [[ address and address.city ]]
+ [[ address and address.country_id.name ]]
+ Tel : [[ address and address.phone ]]
+ E-mail : [[ address and address.email ]]
+ Salesman : [[ o.user_id.name ]]
+ Sale Date : [[ o.date_order ]]
+ Refund Receipt: [[o.name]]
+
+
+
+
+
+
+
+ Description
+
+
+ Qty
+
+
+ Price
+
+
+
+
+ [[ repeatIn(o.lines,'line') ]]
+
+
+
+
+ [[ line.product_id.name ]]
+
+
+ [[o.state=='cancel' and o.statement_ids and '-' or '']][['%.f' % line.qty ]]
+
+
+ [[o.state=='cancel' and o.statement_ids and '-' or '']][[ '%.2f' % net(line.id) ]] [[ line and line.discount == 0.0 and removeParentNode('font') ]] ([[ '%.f' % line.discount ]]%)
+
+
+
+
+
+
+
+ Disc :
+
+
+ [[o.state=='cancel' and o.statement_ids and '-' or '']][[ '%.2f' % (disc(o.id) or 0.0,) ]]
+
+
+
+
+ Total :
+
+
+ [[o.state=='cancel' and o.statement_ids and '-' or '']][['%.2f' % o.amount_total ]] [[ o.pricelist_id.currency_id.name ]]
+
+
+
+ [[ get_journal_amt(o)[0] ]] : [[ get_journal_amt(o)[1] ]]
+
+
+
diff --git a/addons/point_of_sale/report/pos_receipt_without_remboursment.py b/addons/point_of_sale/report/pos_receipt_without_remboursment.py
new file mode 100644
index 00000000000..843041f3863
--- /dev/null
+++ b/addons/point_of_sale/report/pos_receipt_without_remboursment.py
@@ -0,0 +1,81 @@
+# -*- encoding: utf-8 -*-
+##############################################################################
+#
+# OpenERP, Open Source Management Solution
+# Copyright (C) 2004-2009 Tiny SPRL (). All Rights Reserved
+# $Id$
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU 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 General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
+#
+##############################################################################
+
+import time
+from report import report_sxw
+import pooler
+
+
+class order(report_sxw.rml_parse):
+
+ def __init__(self, cr, uid, name, context):
+ super(order, self).__init__(cr, uid, name, context)
+
+ user = pooler.get_pool(cr.dbname).get('res.users').browse(cr, uid, uid)
+ partner = user.company_id.partner_id
+
+ self.localcontext.update({
+ 'time': time,
+ 'disc': self.discount,
+ 'net': self.netamount,
+ 'get_journal_amt': self._get_journal_amt,
+ 'address': partner.address and partner.address[0] or False,
+ })
+
+ def netamount(self, order_line_id):
+ sql = 'select (qty*price_unit) as net_price from pos_order_line where id = %s'
+ self.cr.execute(sql, (order_line_id,))
+ res = self.cr.fetchone()
+ return res[0]
+
+ def discount(self, order_id):
+ sql = 'select discount, price_unit, qty from pos_order_line where order_id = %s '
+ self.cr.execute(sql, (order_id,))
+ res = self.cr.fetchall()
+ dsum = 0
+ for line in res:
+ if line[0] != 0:
+ dsum = dsum +(line[2] * (line[0]*line[1]/100))
+ return dsum
+
+ def _get_journal_amt(self, order_id):
+ lst=[]
+ sql = """ select aj.name from account_bank_statement as abs
+ LEFT JOIN account_bank_statement_line as absl ON abs.id = absl.statement_id
+ LEFT JOIN account_journal as aj ON aj.id = abs.journal_id
+ WHERE absl.pos_statement_id = %d"""%(order_id.id)
+ self.cr.execute(sql)
+ res = self.cr.fetchone()
+ lst.append(res[0])
+ sql2 = """ select sum(absl.amount) as amt from account_bank_statement as abs
+ LEFT JOIN account_bank_statement_line as absl ON abs.id = absl.statement_id
+ LEFT JOIN account_journal as aj ON aj.id = abs.journal_id
+ where aj.name = '%s' """%(res[0])
+ self.cr.execute(sql2)
+ res1 = self.cr.fetchone()
+ lst.append(res1[0])
+ return lst
+
+report_sxw.report_sxw('report.pos.receipt.without.remboursment', 'pos.order', 'addons/point_of_sale/report/pos_receipt_without_remboursment.rml', parser=order, header=False)
+
+# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
+
diff --git a/addons/point_of_sale/report/pos_receipt_without_remboursment.rml b/addons/point_of_sale/report/pos_receipt_without_remboursment.rml
new file mode 100644
index 00000000000..d863efd40f3
--- /dev/null
+++ b/addons/point_of_sale/report/pos_receipt_without_remboursment.rml
@@ -0,0 +1,138 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ [[ repeatIn(objects,'o') ]]
+ [[ repeatIn(objects,'o') ]]
+ [[o.user_id.company_id.name]]
+ [[ address and address.street ]], [[ address and address.zip ]] [[ address and address.city ]]
+ [[ address and address.country_id.name ]]
+ Tel : [[ address and address.phone ]]
+ E-mail : [[ address and address.email ]]
+ Salesman : [[ o.user_id.name ]]
+ Sale Date : [[ o.date_order ]]
+ Purchase Voucher : [[o.name]]
+
+
+
+
+
+
+
+ Description
+
+
+ Qty
+
+
+ Price
+
+
+
+
+ [[ repeatIn(o.lines,'line') ]]
+
+
+
+
+ [[ line.product_id.name ]]
+
+
+ [[o.state=='cancel' and o.statement_ids and '-' or '']][['%.f' % line.qty ]]
+
+
+ [[o.state=='cancel' and o.statement_ids and '-' or '']][[ '%.2f' % net(line.id) ]] [[ line and line.discount == 0.0 and removeParentNode('font') ]] ([[ '%.f' % line.discount ]]%)
+
+
+
+
+
+
+
+ Disc :
+
+
+ [[o.state=='cancel' and o.statement_ids and '-' or '']][[ '%.2f' % (disc(o.id) or 0.0,) ]]
+
+
+
+
+ Total :
+
+
+ [[o.state=='cancel' and o.statement_ids and '-' or '']][['%.2f' % o.amount_total ]] [[ o.pricelist_id.currency_id.name ]]
+
+
+
+ [[ get_journal_amt(o)[0] ]] : [[ get_journal_amt(o)[1] ]]
+
+
+ [[ repeatIn((o.state=='cancel' and o.statement_ids) and [1] or [], 'p') ]]
+
+ Ce bon est valide jusqu'au [[ time.strftime('%d/%m/%Y', time.strptime(o.date_validity,'%Y-%m-%d')) ]].
+
+
+
+
+
diff --git a/addons/point_of_sale/report/pos_sales_user.py b/addons/point_of_sale/report/pos_sales_user.py
new file mode 100644
index 00000000000..034587a8ae4
--- /dev/null
+++ b/addons/point_of_sale/report/pos_sales_user.py
@@ -0,0 +1,58 @@
+# -*- encoding: utf-8 -*-
+##############################################################################
+#
+# OpenERP, Open Source Management Solution
+# Copyright (C) 2004-2009 Tiny SPRL (). All Rights Reserved
+# $Id$
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU 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 General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
+#
+##############################################################################
+import time
+from report import report_sxw
+
+
+class pos_sales_user(report_sxw.rml_parse):
+
+ def __init__(self, cr, uid, name, context):
+ super(pos_sales_user, self).__init__(cr, uid, name, context)
+ self.total = 0.0
+ self.localcontext.update({
+ 'time': time,
+ 'get_data':self._get_data,
+
+ })
+
+ def _get_data(self,form):
+ dt1 = form['date_start'] + ' 00:00:00'
+ dt2 = form['date_end'] + ' 23:59:59'
+ data={}
+ self.cr.execute("select po.name as pos,po.date_order,ru.name as user,po.state,rc.name " \
+ "from pos_order as po,res_users as ru,res_company as rc " \
+ "where po.date_order >= %s and po.date_order <= %s " \
+ "and po.company_id=rc.id and po.user_id=ru.id and po.user_id in %s " \
+ ,(dt1,dt2,tuple(form['user_id'][0][-1])))
+
+ data = self.cr.dictfetchall()
+ return data
+
+report_sxw.report_sxw('report.pos.sales.user', 'pos.order', 'addons/point_of_sale/report/pos_sales_user.rml', parser=pos_sales_user)
+
+
+
+
+
+
+
+
diff --git a/addons/point_of_sale/report/pos_sales_user.rml b/addons/point_of_sale/report/pos_sales_user.rml
new file mode 100644
index 00000000000..b6a3dae9685
--- /dev/null
+++ b/addons/point_of_sale/report/pos_sales_user.rml
@@ -0,0 +1,188 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/addons/point_of_sale/report/pos_sales_user_today.py b/addons/point_of_sale/report/pos_sales_user_today.py
new file mode 100644
index 00000000000..4e06a936116
--- /dev/null
+++ b/addons/point_of_sale/report/pos_sales_user_today.py
@@ -0,0 +1,58 @@
+# -*- encoding: utf-8 -*-
+##############################################################################
+#
+# OpenERP, Open Source Management Solution
+# Copyright (C) 2004-2009 Tiny SPRL (). All Rights Reserved
+# $Id$
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU 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 General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
+#
+##############################################################################
+import time
+from report import report_sxw
+
+
+class pos_sales_user_today(report_sxw.rml_parse):
+
+ def __init__(self, cr, uid, name, context):
+ super(pos_sales_user_today, self).__init__(cr, uid, name, context)
+ self.total = 0.0
+ self.localcontext.update({
+ 'time': time,
+ 'get_data':self._get_data,
+
+ })
+
+ def _get_data(self,form):
+ data={}
+ ids = form['user_id'][0][-1]
+ idss = map(str, ids)
+
+ self.cr.execute("select po.name as pos,po.date_order,ru.name as user,po.state,rc.name " \
+ "from pos_order as po,res_users as ru,res_company as rc " \
+ "where to_char(date_trunc('day',po.date_order),'YYYY-MM-DD')::date = current_date " \
+ "and po.company_id=rc.id and po.user_id=ru.id and po.user_id in (%s)"% (",".join(idss), ))
+
+ data = self.cr.dictfetchall()
+ return data
+
+report_sxw.report_sxw('report.pos.sales.user.today', 'pos.order', 'addons/point_of_sale/report/pos_sales_user_today.rml', parser=pos_sales_user_today)
+
+
+
+
+
+
+
+
diff --git a/addons/point_of_sale/report/pos_sales_user_today.rml b/addons/point_of_sale/report/pos_sales_user_today.rml
new file mode 100644
index 00000000000..7db76e33ff4
--- /dev/null
+++ b/addons/point_of_sale/report/pos_sales_user_today.rml
@@ -0,0 +1,187 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/addons/point_of_sale/report/pos_users_product.py b/addons/point_of_sale/report/pos_users_product.py
new file mode 100644
index 00000000000..2fcf35988c9
--- /dev/null
+++ b/addons/point_of_sale/report/pos_users_product.py
@@ -0,0 +1,66 @@
+# -*- encoding: utf-8 -*-
+##############################################################################
+#
+# OpenERP, Open Source Management Solution
+# Copyright (C) 2004-2009 Tiny SPRL (). All Rights Reserved
+# $Id$
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU 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 General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
+#
+##############################################################################
+import time
+from report import report_sxw
+
+
+class pos_user_product(report_sxw.rml_parse):
+
+ def __init__(self, cr, uid, name, context):
+ super(pos_user_product, self).__init__(cr, uid, name, context)
+ self.total = 0.0
+ self.localcontext.update({
+ 'time': time,
+ 'get_data':self._get_data,
+ 'get_user':self._get_user,
+ 'get_total':self._get_total,
+
+ })
+ def _get_data(self,o):
+ data={}
+ sql1=""" SELECT distinct(o.id) from account_bank_statement s, account_bank_statement_line l,pos_order o,pos_order_line i where i.order_id=o.id and o.state='paid' and l.statement_id=s.id and l.pos_statement_id=o.id and s.id=%d"""%(o.id)
+ self.cr.execute(sql1)
+ data = self.cr.dictfetchall()
+ a_l=[]
+ for r in data:
+ a_l.append(r['id'])
+ a = ','.join(map(str,a_l))
+ if len(a):
+ sql2="""SELECT sum(qty) as qty,l.price_unit*sum(l.qty) as amt,t.name as name from product_product p, product_template t, pos_order_line l where order_id in (%s) and p.product_tmpl_id=t.id and l.product_id=p.id group by t.name, l.price_unit"""%(a)
+ self.cr.execute(sql2)
+ data = self.cr.dictfetchall()
+ for d in data:
+ self.total += d['amt']
+ return data
+
+ def _get_user(self,object):
+ for o in object :
+ sql = """select ru.name from account_bank_statement as abs,res_users ru
+ where abs.user_id = ru.id
+ and abs.id = %d"""%(o.id)
+ self.cr.execute(sql)
+ data = self.cr.fetchone()
+ return data[0]
+ def _get_total(self):
+ return self.total
+
+report_sxw.report_sxw('report.pos.user.product', 'account.bank.statement', 'addons/statement/report/pos_users_product.rml', parser=pos_user_product)
diff --git a/addons/point_of_sale/report/pos_users_product.py.WORK b/addons/point_of_sale/report/pos_users_product.py.WORK
new file mode 100644
index 00000000000..f26be9c7172
--- /dev/null
+++ b/addons/point_of_sale/report/pos_users_product.py.WORK
@@ -0,0 +1,71 @@
+# -*- encoding: utf-8 -*-
+##############################################################################
+#
+# OpenERP, Open Source Management Solution
+# Copyright (C) 2004-2009 Tiny SPRL (). All Rights Reserved
+# $Id$
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU 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 General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
+#
+##############################################################################
+import time
+from report import report_sxw
+
+
+class pos_user_product(report_sxw.rml_parse):
+
+ def __init__(self, cr, uid, name, context):
+ super(pos_user_product, self).__init__(cr, uid, name, context)
+ self.total = 0.0
+ self.localcontext.update({
+ 'time': time,
+ 'get_data':self._get_data,
+ 'get_user':self._get_user,
+ 'get_total':self._get_total,
+
+ })
+ def _get_data(self,object):
+ data={}
+ for o in object :
+ sql1=""" SELECT distinct(o.id) from account_bank_statement s, account_bank_statement_line l,pos_order o,pos_order_line i where i.order_id=o.id and o.state in ('paid','invoiced') and l.statement_id=s.id and l.pos_statement_id=o.id and s.id=%d"""%(o.id)
+ print sql1
+ self.cr.execute(sql1)
+ data = self.cr.dictfetchall()
+ print "DATA",data
+ a_l=[]
+ for r in data:
+ if r['id']:
+ a_l.append(r['id'])
+ a = ','.join(map(str,a_l))
+ print a_l, a
+ if len(a_l):
+ sql2="""SELECT sum(qty) as qty,l.price_unit*sum(l.qty) as amt,t.name as name from product_product p, product_template t, pos_order_line l where order_id in (%s) and p.product_tmpl_id=t.id and l.product_id=p.id group by t.name, l.price_unit"""%(a)
+ self.cr.execute(sql2)
+ data = self.cr.dictfetchall()
+ for d in data:
+ self.total += d['amt']
+ return data
+
+ def _get_user(self,object):
+ for o in object :
+ sql = """select ru.name from account_bank_statement as abs,res_users ru
+ where abs.user_id = ru.id
+ and abs.id = %d"""%(o.id)
+ self.cr.execute(sql)
+ data = self.cr.fetchone()
+ return data[0]
+ def _get_total(self):
+ return self.total
+
+report_sxw.report_sxw('report.pos.user.product', 'account.bank.statement', 'addons/statement/report/pos_users_product.rml', parser=pos_user_product)
diff --git a/addons/point_of_sale/report/pos_users_product.rml b/addons/point_of_sale/report/pos_users_product.rml
new file mode 100644
index 00000000000..cbb309ceef2
--- /dev/null
+++ b/addons/point_of_sale/report/pos_users_product.rml
@@ -0,0 +1,233 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+[[ repeatIn(objects,'o') ]]
+
+
+
+
+
+
+
+
+
+
+
+ My CashBoxes
+ account.bank.statement
+ form
+ tree,form
+
+ [('user_id','=',uid)]
+
+
+
+ tree
+
+
+
+
+
+ form
+
+
+
+
+
+
+
+
+
+ My Cashboxes to Close
+ account.bank.statement
+ form
+ tree,form
+
+ [('state','=','open'), ('user_id','=',uid)]
+
+
+
+
+
+ tree
+
+
+
+
+
+ form
+
+
+
+
+
+
+
+ account.bank.statement.form
+ account.bank.statement
+ form
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ account.bank.statement.tree
+ account.bank.statement
+ tree
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Open a CashBox
+ account.bank.statement
+ form
+
+ [('state','=','draft'),('user_id','=',uid)]
+
+
+
+
+ tree
+
+
+
+
+
+ form
+
+
+
+
+
+
+
+
+
+ All Cashboxes
+ ir.actions.act_window
+ account.bank.statement
+ form
+
+
+
+ tree
+
+
+
+
+
+ form
+
+
+
+
+
+
+ All My Cashboxes
+ ir.actions.act_window
+ account.bank.statement
+ form
+ [('user_id','=',uid)]
+
+
+
+ tree
+
+
+
+
+
+
+ form
+
+
+
+
+
+
+
+ Cashboxes to Close
+ ir.actions.act_window
+ account.bank.statement
+ form
+ tree,form
+ [('state','=','draft')]
+
+
+
+ tree
+
+
+
+
+
+ form
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/addons/point_of_sale/statement_wizard.xml b/addons/point_of_sale/statement_wizard.xml
new file mode 100644
index 00000000000..f3bffb15ce1
--- /dev/null
+++ b/addons/point_of_sale/statement_wizard.xml
@@ -0,0 +1,42 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/addons/point_of_sale/stock.py b/addons/point_of_sale/stock.py
index 206497a24e9..95630569a7c 100644
--- a/addons/point_of_sale/stock.py
+++ b/addons/point_of_sale/stock.py
@@ -1,21 +1,22 @@
-# -*- coding: utf-8 -*-
+# -*- encoding: utf-8 -*-
##############################################################################
-#
+#
# OpenERP, Open Source Management Solution
-# Copyright (C) 2004-2010 Tiny SPRL ().
+# Copyright (C) 2004-2009 Tiny SPRL (). All Rights Reserved
+# $Id$
#
# 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.
+# it under the terms of the GNU 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.
+# GNU 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 .
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
#
##############################################################################
@@ -23,31 +24,14 @@ from osv import osv, fields
import time
import netsvc
-class stock_move(osv.osv):
- _inherit = 'stock.move'
-
- _columns = {
- 'pos_line_id': fields.many2one('pos.order.line',
- 'Pos Order Line', ondelete='set null', select=True,
- readonly=True),
- }
-
-stock_move()
-
class stock_picking(osv.osv):
_inherit = 'stock.picking'
_columns = {
'pos_order': fields.many2one('pos.order', 'Pos order'),
+ # 'company_id':fields.many2one('res.company', 'Company', required=True),
}
-
- def _get_discount_invoice(self, cursor, user, move_line):
- if move_line.pos_line_id:
- return move_line.pos_line_id.discount
- return super(stock_picking, self)._get_discount_invoice(cursor, user,
- move_line)
-
stock_picking()
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
diff --git a/addons/point_of_sale/wizard/__init__.py b/addons/point_of_sale/wizard/__init__.py
index 0d77b783e5d..1ff9c124861 100644
--- a/addons/point_of_sale/wizard/__init__.py
+++ b/addons/point_of_sale/wizard/__init__.py
@@ -1,21 +1,22 @@
-# -*- coding: utf-8 -*-
+# -*- encoding: utf-8 -*-
##############################################################################
-#
+#
# OpenERP, Open Source Management Solution
-# Copyright (C) 2004-2010 Tiny SPRL ().
+# Copyright (C) 2004-2009 Tiny SPRL (). All Rights Reserved
+# $Id$
#
# 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.
+# it under the terms of the GNU 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.
+# GNU 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 .
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
#
##############################################################################
@@ -27,6 +28,16 @@ import wizard_confirm
import wizard_discount
import wizard_get_sale
import wizard_scan_product
-
-from wizard import except_wizard
+import wizard_receipt
+import wizard_return
+import wizard_pos_payment_report
+import wizard_pos_sales_user
+import wizard_pos_sales_user_today
+import wizard_pos_payment_report_date
+import wizard_pos_payment_report_user
+import wizard_pos_sales_user_current_user
+import wizard_pos_details
+import wizard_open_statement
+import wizard_all_closed_cashbox_of_the_day
+# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
diff --git a/addons/point_of_sale/wizard/wizard_add_product.py b/addons/point_of_sale/wizard/wizard_add_product.py
index c4776e86f2a..0daa0bdf0db 100644
--- a/addons/point_of_sale/wizard/wizard_add_product.py
+++ b/addons/point_of_sale/wizard/wizard_add_product.py
@@ -1,21 +1,22 @@
-# -*- coding: utf-8 -*-
+# -*- encoding: utf-8 -*-
##############################################################################
-#
-# OpenERP, Open Source Management Solution
-# Copyright (C) 2004-2010 Tiny SPRL ().
+#
+# OpenERP, Open Source Management Solution
+# Copyright (C) 2004-2009 Tiny SPRL (). All Rights Reserved
+# $Id$
#
# 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.
+# it under the terms of the GNU 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.
+# GNU 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 .
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
#
##############################################################################
diff --git a/addons/point_of_sale/wizard/wizard_all_closed_cashbox_of_the_day.py b/addons/point_of_sale/wizard/wizard_all_closed_cashbox_of_the_day.py
new file mode 100644
index 00000000000..bdb7f72cb93
--- /dev/null
+++ b/addons/point_of_sale/wizard/wizard_all_closed_cashbox_of_the_day.py
@@ -0,0 +1,40 @@
+# -*- encoding: utf-8 -*-
+##############################################################################
+#
+# OpenERP, Open Source Management Solution
+# Copyright (C) 2004-2009 Tiny SPRL (). All Rights Reserved
+# $Id$
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU 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 General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
+#
+##############################################################################
+
+import pooler
+import netsvc
+import wizard
+import time
+
+
+class wizard_all_closed_cashbox_of_the_day(wizard.interface):
+ states = {
+ 'init': {
+ 'actions': [],
+ 'result': {'type':'print', 'report':'all.closed.cashbox.of.the.day', 'state':'end'}
+ },
+ }
+
+wizard_all_closed_cashbox_of_the_day('all.closed.cashbox.of.the.day')
+
+# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
+
diff --git a/addons/point_of_sale/wizard/wizard_confirm.py b/addons/point_of_sale/wizard/wizard_confirm.py
index 476e2dbfe64..b819c840ae5 100644
--- a/addons/point_of_sale/wizard/wizard_confirm.py
+++ b/addons/point_of_sale/wizard/wizard_confirm.py
@@ -1,45 +1,75 @@
-# -*- coding: utf-8 -*-
+# -*- encoding: utf-8 -*-
##############################################################################
-#
+#
# OpenERP, Open Source Management Solution
-# Copyright (C) 2004-2010 Tiny SPRL ().
+# Copyright (C) 2004-2009 Tiny SPRL (). All Rights Reserved
+# $Id$
#
# 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.
+# it under the terms of the GNU 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.
+# GNU 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 .
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
#
##############################################################################
import wizard
import netsvc
+import pooler
+import time
+_form = """
+
+
+
+"""
+_fields = {}
def _confirm(self, cr, uid, data, context):
- wf_service = netsvc.LocalService("workflow")
+ pool = pooler.get_pool(cr.dbname)
+ company_id=pool.get('res.users').browse(cr,uid,uid).company_id
+ order_obj = pool.get('pos.order')
+ for order_id in order_obj.browse(cr, uid, data['ids'], context=context):
+ if order_id.state =='paid':
+ order_obj.write(cr,uid,[order_id.id],{'journal_entry':True})
+ order_obj.create_account_move(cr, uid, [order_id.id], context=context)
+ wf_service = netsvc.LocalService("workflow")
for i in data['ids']:
wf_service.trg_validate(uid, 'pos.order', i, 'done', cr)
return {}
-
+def _get_state(self, cr, uid, data, context):
+ action = 'invoice'
+ return action
class pos_confirm(wizard.interface):
- states = {
- 'init': {'actions' : [_confirm],
+
+ states = {
+ 'init': {
+ 'actions': [],
'result': {
- 'type': 'state',
- 'state': 'end',
+ 'type': 'form',
+ 'arch': _form,
+ 'fields': _fields,
+ 'state': (('end', 'No','gtk-cancel'),
+ ('open', 'Yes', 'gtk-ok', True)
+ )
}
},
+ 'open': {
+ 'actions': [_confirm],
+ 'result': {
+ 'type': 'state',
+ 'state':'end'}
+ },
}
pos_confirm('pos.confirm')
diff --git a/addons/point_of_sale/wizard/wizard_default_journal.py b/addons/point_of_sale/wizard/wizard_default_journal.py
index 161ef5d3214..bfe59251f45 100644
--- a/addons/point_of_sale/wizard/wizard_default_journal.py
+++ b/addons/point_of_sale/wizard/wizard_default_journal.py
@@ -1,21 +1,22 @@
-# -*- coding: utf-8 -*-
+# -*- encoding: utf-8 -*-
##############################################################################
-#
-# OpenERP, Open Source Management Solution
-# Copyright (C) 2004-2010 Tiny SPRL ().
+#
+# OpenERP, Open Source Management Solution
+# Copyright (C) 2004-2009 Tiny SPRL (). All Rights Reserved
+# $Id$
#
# 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.
+# it under the terms of the GNU 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.
+# GNU 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 .
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
#
##############################################################################
diff --git a/addons/point_of_sale/wizard/wizard_discount.py b/addons/point_of_sale/wizard/wizard_discount.py
index da405cf3d45..035c387793c 100644
--- a/addons/point_of_sale/wizard/wizard_discount.py
+++ b/addons/point_of_sale/wizard/wizard_discount.py
@@ -1,35 +1,42 @@
-# -*- coding: utf-8 -*-
+# -*- encoding: utf-8 -*-
##############################################################################
-#
+#
# OpenERP, Open Source Management Solution
-# Copyright (C) 2004-2010 Tiny SPRL ().
+# Copyright (C) 2004-2009 Tiny SPRL (). All Rights Reserved
+# $Id$
#
# 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.
+# it under the terms of the GNU 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.
+# GNU 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 .
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
#
##############################################################################
-
import pooler
-
import wizard
-
_form = """
"""
+disc_form = """
+
+
+
+
+
+
+"""
+
_fields = {
'discount': {
@@ -40,19 +47,59 @@ _fields = {
},
}
-
-def apply_discount(self, cr, uid, data, context):
- pool = pooler.get_pool(cr.dbname)
- order_ref = pool.get('pos.order')
- order_line_ref = pool.get('pos.order.line')
- for order in order_ref.browse(cr, uid, data['ids'], context=context):
- order_line_ref.write(cr, uid, [line.id for line in order.lines],
- {'discount': data['form']['discount']},
- context=context,)
- return {}
-
+disc_fields = {
+ 'note': {
+ 'string': 'Discount Notes',
+ 'type': 'char',
+ 'size': 128,
+ 'required': True
+ },
+}
class discount_wizard(wizard.interface):
+
+ def apply_discount(self, cr, uid, data, context):
+ pool = pooler.get_pool(cr.dbname)
+ order_ref = pool.get('pos.order')
+ order_line_ref = pool.get('pos.order.line')
+ for order in order_ref.browse(cr, uid, data['ids'], context=context):
+ for line in order.lines :
+ company_discount = order.company_id.company_discount
+ applied_discount =data['form']['discount']
+ if applied_discount == 0.00:
+ notice = 'No Discount'
+ elif company_discount >= applied_discount:
+ notice = 'Minimum Discount'
+ else:
+ notice = data['form']['note']
+ if self.check_discount(cr, uid, data, context) == 'apply_discount':
+ order_line_ref.write(cr, uid, [line.id],
+ {'discount': data['form']['discount'],
+ 'price_ded':line.price_unit*line.qty*(data['form']['discount'] or 0)*0.01 or 0.0,
+ 'notice':notice
+ },
+ context=context,)
+ else :
+ order_line_ref.write(cr, uid, [line.id],
+ {'discount': data['form']['discount'],
+ 'notice': notice,
+ 'price_ded':line.price_unit*line.qty*(data['form']['discount'] or 0)*0.01 or 0.0
+ },
+ context=context,)
+ return {}
+
+ def check_discount(self, cr, uid, data, context):
+ pool = pooler.get_pool(cr.dbname)
+ order_ref = pool.get('pos.order')
+ for order in order_ref.browse(cr, uid, data['ids'], context=context):
+ company_disc = order.company_id.company_discount
+ for line in order.lines :
+ prod_disc = data['form']['discount']
+ if prod_disc <= company_disc :
+ return 'apply_discount'
+ else :
+ return 'disc_discount'
+
states = {
'init': {
'actions': [],
@@ -60,6 +107,23 @@ class discount_wizard(wizard.interface):
'type': 'form',
'arch': _form,
'fields': _fields,
+ 'state': (('end', 'Cancel'),
+ ('check_disc', 'Apply Discount', 'gtk-ok', True)
+ )
+ }
+ },
+
+ 'check_disc': {
+ 'actions': [],
+ 'result': {'type':'choice','next_state':check_discount}
+ },
+
+ 'disc_discount': {
+ 'actions': [],
+ 'result': {
+ 'type': 'form',
+ 'arch': disc_form,
+ 'fields':disc_fields,
'state': (('end', 'Cancel'),
('apply_discount', 'Apply Discount', 'gtk-ok', True)
)
diff --git a/addons/point_of_sale/wizard/wizard_get_sale.py b/addons/point_of_sale/wizard/wizard_get_sale.py
index ac758dfb445..de686c11d49 100644
--- a/addons/point_of_sale/wizard/wizard_get_sale.py
+++ b/addons/point_of_sale/wizard/wizard_get_sale.py
@@ -1,21 +1,22 @@
-# -*- coding: utf-8 -*-
+# -*- encoding: utf-8 -*-
##############################################################################
-#
-# OpenERP, Open Source Management Solution
-# Copyright (C) 2004-2010 Tiny SPRL ().
+#
+# OpenERP, Open Source Management Solution
+# Copyright (C) 2004-2009 Tiny SPRL (). All Rights Reserved
+# $Id$
#
# 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.
+# it under the terms of the GNU 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.
+# GNU 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 .
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
#
##############################################################################
diff --git a/addons/point_of_sale/wizard/wizard_open_statement.py b/addons/point_of_sale/wizard/wizard_open_statement.py
new file mode 100644
index 00000000000..09205a97b08
--- /dev/null
+++ b/addons/point_of_sale/wizard/wizard_open_statement.py
@@ -0,0 +1,147 @@
+# -*- encoding: utf-8 -*-
+##############################################################################
+#
+# OpenERP, Open Source Management Solution
+# Copyright (C) 2004-2009 Tiny SPRL (). All Rights Reserved
+# $Id$
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU 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 General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
+#
+##############################################################################
+
+import pooler
+import wizard
+from tools.translate import _
+import time
+
+statement_form = """
+
+
+
+"""
+statement_form_close = """
+
+
+
+"""
+
+statement_fields = {}
+
+def _close_statement(self, cr, uid, data, context):
+ pool = pooler.get_pool(cr.dbname)
+ company_id=pool.get('res.users').browse(cr,uid,uid).company_id.id
+ statement_obj = pool.get('account.bank.statement')
+ singer_obj = pool.get('singer.statement')
+ journal_obj=pool.get('account.journal')
+ journal_lst=journal_obj.search(cr,uid,[('company_id','=',company_id),('auto_cash','=',True),('check_dtls','=',False)])
+ journal_ids=journal_obj.browse(cr,uid, journal_lst)
+ for journal in journal_ids:
+ ids = statement_obj.search(cr, uid, [('state','!=','confirm'),('user_id','=',uid),('journal_id','=',journal.id)])
+ statement_obj.button_confirm(cr,uid,ids)
+ return {}
+def _open_statement(self, cr, uid, data, context):
+ pool = pooler.get_pool(cr.dbname)
+ company_id=pool.get('res.users').browse(cr,uid,uid).company_id.id
+ statement_obj = pool.get('account.bank.statement')
+ singer_obj = pool.get('singer.statement')
+ journal_obj=pool.get('account.journal')
+ journal_lst=journal_obj.search(cr,uid,[('company_id','=',company_id),('auto_cash','=',True)])
+ journal_ids=journal_obj.browse(cr,uid, journal_lst)
+ for journal in journal_ids:
+ ids = statement_obj.search(cr, uid, [('state','!=','confirm'),('user_id','=',uid),('journal_id','=',journal.id)])
+ if len(ids):
+ raise wizard.except_wizard(_('Message'),_('You can not open a Cashbox for "%s". \n Please close the cashbox related to. '%(journal.name) ))
+ sql = """ Select id from account_bank_statement
+ where journal_id=%d
+ and company_id =%d
+ order by id desc limit 1"""%(journal.id,company_id)
+ singer_ids=None
+ cr.execute(sql)
+ st_id = cr.fetchone()
+ number=''
+ if journal.statement_sequence_id:
+ number = pool.get('ir.sequence').get_id(cr, uid, journal.id)
+ else:
+ number = pool.get('ir.sequence').get(cr, uid,
+ 'account.bank.statement')
+
+# statement_id=statement_obj.create(cr,uid,{'journal_id':journal.id,
+# 'company_id':company_id,
+# 'user_id':uid,
+# 'state':'open',
+# 'name':number
+# })
+ period=statement_obj._get_period(cr,uid,context) or None
+ cr.execute("INSERT INTO account_bank_statement(journal_id,company_id,user_id,state,name, period_id,date) VALUES(%d,%d,%d,'open','%s',%d,'%s')"%(journal.id,company_id,uid,number, period, time.strftime('%Y-%m-%d %H:%M:%S')))
+ cr.commit()
+ cr.execute("select id from account_bank_statement where journal_id=%d and company_id=%d and user_id=%d and state='open' and name='%s'"%(journal.id,company_id,uid,number))
+ statement_id=cr.fetchone()[0]
+ if st_id:
+ statemt_id=statement_obj.browse(cr,uid,st_id[0])
+ if statemt_id and statemt_id.ending_details_ids:
+ statement_obj.write(cr, uid,[statement_id], {'balance_start':statemt_id.balance_end,
+ 'state':'open'})
+ if statemt_id.ending_details_ids:
+ for i in statemt_id.ending_details_ids:
+ c=singer_obj.create(cr,uid, { 'pieces':i.pieces,
+ 'number':i.number,
+ 'starting_id':statement_id,
+ })
+ cr.commit()
+ return {}
+
+class statement_open(wizard.interface):
+ states = {
+ 'init': {
+ 'actions': [],
+ 'result': {
+ 'type': 'form',
+ 'arch': statement_form,
+ 'fields': statement_fields,
+ 'state': (('end', 'No','gtk-cancel'),
+ ('open', 'Yes', 'gtk-ok', True)
+ )
+ }
+ },
+ 'open': {
+ 'actions': [_open_statement],
+ 'result': {
+ 'type': 'state',
+# 'action' :_open_statement,
+ 'state':'end'}
+ },
+ }
+statement_open('statement.open')
+class statement_close(wizard.interface):
+ states = {
+ 'init': {
+ 'actions': [],
+ 'result': {
+ 'type': 'form',
+ 'arch': statement_form_close,
+ 'fields': statement_fields,
+ 'state': (('end', 'No','gtk-cancel'),
+ ('open', 'Yes', 'gtk-ok', True)
+ )
+ }
+ },
+ 'open': {
+ 'actions': [_close_statement],
+ 'result': {
+ 'type': 'state',
+ 'state':'end'}
+ },
+ }
+statement_close('statement.close')
+# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
diff --git a/addons/point_of_sale/wizard/wizard_pos_details.py b/addons/point_of_sale/wizard/wizard_pos_details.py
new file mode 100644
index 00000000000..80a0593c08e
--- /dev/null
+++ b/addons/point_of_sale/wizard/wizard_pos_details.py
@@ -0,0 +1,67 @@
+# -*- encoding: utf-8 -*-
+##############################################################################
+#
+# OpenERP, Open Source Management Solution
+# Copyright (C) 2004-2008 Tiny SPRL (). All Rights Reserved
+# $Id$
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU 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 General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
+#
+##############################################################################
+
+from osv import fields
+from osv import osv
+import time
+import ir
+from mx import DateTime
+import datetime
+import pooler
+from tools import config
+import wizard
+import netsvc
+
+
+pos_details_res_form= """
+
+
+
+
+"""
+
+pos_details_res_field= {
+ 'date_start': {'string':'Start Date','type':'date','required': True,'default': lambda *a: time.strftime('%Y-%m-%d')},
+ 'date_end': {'string':'End Date','type':'date','required': True,'default': lambda *a: time.strftime('%Y-%m-%d')},
+
+
+}
+
+
+class wizard_pos_details(wizard.interface):
+
+ states = {
+ 'init' : {
+ 'actions' : [],
+ 'result' : {'type' : 'form',
+ 'arch' : pos_details_res_form,
+ 'fields' : pos_details_res_field,
+ 'state' : [('end', 'Cancel','gtk-cancel'),('print_report', 'Print Report','gtk-print') ]}
+ },
+ 'print_report' : {
+ 'actions' : [],
+ 'result' : {'type' : 'print',
+ 'report':'pos.details',
+ 'state' : 'end'}
+ },
+ }
+wizard_pos_details('pos.details')
diff --git a/addons/point_of_sale/wizard/wizard_pos_payment.py b/addons/point_of_sale/wizard/wizard_pos_payment.py
index d41c0405b5a..b184d1184be 100644
--- a/addons/point_of_sale/wizard/wizard_pos_payment.py
+++ b/addons/point_of_sale/wizard/wizard_pos_payment.py
@@ -1,21 +1,22 @@
-# -*- coding: utf-8 -*-
+# -*- encoding: utf-8 -*-
##############################################################################
-#
+#
# OpenERP, Open Source Management Solution
-# Copyright (C) 2004-2010 Tiny SPRL ().
+# Copyright (C) 2004-2009 Tiny SPRL (). All Rights Reserved
+# $Id$
#
# 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.
+# it under the terms of the GNU 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.
+# GNU 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 .
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
#
##############################################################################
@@ -23,12 +24,14 @@ import pooler
import netsvc
import wizard
import time
+from decimal import Decimal
def _get_journal(self, cr, uid, context):
pool = pooler.get_pool(cr.dbname)
obj = pool.get('account.journal')
- ids = obj.search(cr, uid, [('type', '=', 'cash')])
+ c=pool.get('res.users').browse(cr,uid,uid).company_id.id
+ ids = obj.search(cr, uid, [('type', '=', 'cash'), ('company_id', '=', c)])
res = obj.read(cr, uid, ids, ['id', 'name'], context)
res = [(r['id'], r['name']) for r in res]
return res
@@ -36,67 +39,64 @@ def _get_journal(self, cr, uid, context):
payment_form = """
+
-
-
+
+
+
+
+
+
"""
payment_fields = {
'amount': {'string': 'Amount', 'type': 'float', 'required': True},
+ 'is_acc': {'string': 'Accompte', 'type': 'boolean'},
'invoice_wanted': {'string': 'Invoice', 'type': 'boolean'},
'journal': {'string': 'Journal',
- 'type': 'selection',
- 'selection': _get_journal,
- 'required': True,
- },
- 'payment_id': {'string': 'Payment Term', 'type': 'many2one', 'relation': 'account.payment.term', 'required': True},
+ 'type': 'selection',
+ 'selection': _get_journal,
+ 'required': True,
+ },
'payment_date': {'string': 'Payment date', 'type': 'date', 'required': True},
- 'payment_name': {'string': 'Payment name', 'type': 'char', 'size': '32'},
- 'payment_nb': {'string': 'Piece number', 'type': 'char', 'size': '32'},
+ 'payment_name': {'string': 'Payment name', 'type': 'char', 'size': '32', 'required':True, 'default':'Payment'},
+ 'num_sale': {'string': 'Num.File', 'type': 'char', 'size': '32'},
+ 'product_id': {'string':'Acompte','type': 'many2one', 'relation': 'product.product'},
}
def _pre_init(self, cr, uid, data, context):
-
def _get_journal(pool, order):
j_obj = pool.get('account.journal')
-
- journal_to_fetch = 'DEFAULT'
- if order.amount_total < 0:
- journal_to_fetch = 'GIFT'
+ c = pool.get('res.users').browse(cr,uid,uid).company_id.id
+ journal = j_obj.search(cr, uid, [('type', '=', 'cash'), ('company_id', '=', c)])
+ if journal:
+ journal = journal[0]
else:
- if order.amount_paid > 0:
- journal_to_fetch = 'REBATE'
-
- pos_config_journal = pool.get('pos.config.journal')
- ids = pos_config_journal.search(cr, uid, [('code', '=', journal_to_fetch)])
- objs = pos_config_journal.browse(cr, uid, ids)
- journal = None
- if objs:
- journal = objs[0].journal_id.id
- else:
- existing = [payment.journal_id.id for payment in order.payments]
- ids = j_obj.search(cr, uid, [('type', '=', 'cash')])
- for i in ids:
- if i not in existing:
- journal = i
- break
- if not journal:
- journal = ids[0]
-
+ journal = None
return journal
+ wf_service = netsvc.LocalService("workflow")
+ # wf_service.trg_validate(uid, 'pos.order', data['id'], 'start_payment', cr)
+
pool = pooler.get_pool(cr.dbname)
order = pool.get('pos.order').browse(cr, uid, data['id'], context)
-
- # get amount to pay:
+ #get amount to pay
+ #amount = Decimal(str(order.amount_total)) - Decimal(str(order.amount_paid))
amount = order.amount_total - order.amount_paid
+ if amount<=0:
+ context.update({'flag':True})
+ pool.get('pos.order').action_paid(cr,uid,data['ids'],context)
+ elif order.amount_paid > 0:
+ pool.get('pos.order').write(cr, uid, data['id'],{'state':'advance'})
+
+
# get journal:
journal = _get_journal(pool, order)
@@ -113,8 +113,13 @@ def _pre_init(self, cr, uid, data, context):
def _add_pay(self, cr, uid, data, context):
pool = pooler.get_pool(cr.dbname)
order_obj = pool.get('pos.order')
+ jrnl_obj = pool.get('account.journal')
result = data['form']
invoice_wanted = data['form']['invoice_wanted']
+ jrnl_used=False
+ if data['form'] and data['form'].get('journal',False):
+ jrnl_used=jrnl_obj.browse(cr,uid,data['form']['journal'])
+
# add 'invoice_wanted' in 'pos.order'
order_obj.write(cr, uid, [data['id']], {'invoice_wanted': invoice_wanted})
@@ -122,16 +127,6 @@ def _add_pay(self, cr, uid, data, context):
return {}
-def _validate(self, cr, uid, data, context):
- pool = pooler.get_pool(cr.dbname)
- order_obj = pool.get('pos.order')
- order = order_obj.browse(cr, uid, data['id'], context)
-# if not order.amount_total:
-# return 'receipt'
- order_obj.test_order_lines(cr, uid, order, context=context)
- return {}
-
-
def _check(self, cr, uid, data, context):
"""Check the order:
if the order is not paid: continue payment,
@@ -140,61 +135,42 @@ def _check(self, cr, uid, data, context):
pool = pooler.get_pool(cr.dbname)
order_obj = pool.get('pos.order')
order = order_obj.browse(cr, uid, data['id'], context)
+ amount = order.amount_total - order.amount_paid
+ if amount<=0:
+ context.update({'flag':True})
+ pool.get('pos.order').action_paid(cr,uid,data['ids'],context)
+
action = 'ask_pay'
- if order.state == 'paid':
+ if order_obj.test_paid(cr, uid, [data['id']]):
if order.partner_id:
if order.invoice_wanted:
action = 'invoice'
else:
action = 'paid'
- else:
+ elif order.date_payment:
action = 'receipt'
+ else:
+ action = 'paid'
return action
-def _test_no_line(self, cr, uid, data, context):
- pool = pooler.get_pool(cr.dbname)
- order = pool.get('pos.order').browse(cr, uid, data['id'], context)
-
- if not order.lines:
- raise wizard.except_wizard(_('Error'), _('No order lines defined for this sale.'))
-
- if not order.lines:
- raise wizard.except_wizard(_('Error'), _('No order lines defined for this sale.'))
-
- return {}
-
-
def create_invoice(self, cr, uid, data, context):
- pool = pooler.get_pool(cr.dbname)
- order_obj = pool.get('pos.order')
- order = order_obj.browse(cr, uid, data['id'], context)
- if not order.invoice_id:
- inv_id = order_obj.action_invoice(cr, uid, [data['id']])
- #raise wizard.except_wizard(_('Error !'), _('Please create an invoice for this sale.'))
-# wf_service = netsvc.LocalService("workflow")
-# for i in data['ids']:
-# wf_service.trg_validate(uid, 'pos.order', i, 'invoice', cr)
+ wf_service = netsvc.LocalService("workflow")
+ for i in data['ids']:
+ wf_service.trg_validate(uid, 'pos.order', i, 'invoice', cr)
return {}
-
-def create_invoice(self, cr, uid, data, context):
- pool = pooler.get_pool(cr.dbname)
- order_obj = pool.get('pos.order')
- order = order_obj.browse(cr, uid, data['id'], context)
- if not order.invoice_id:
- inv_id = order_obj.action_invoice(cr, uid, [data['id']])
- #raise wizard.except_wizard(_('Error !'), _('Please create an invoice for this sale.'))
-# wf_service = netsvc.LocalService("workflow")
-# for i in data['ids']:
-# wf_service.trg_validate(uid, 'pos.order', i, 'invoice', cr)
+def _trigger_wkf(self, cr, uid, data, context):
+ wf_service = netsvc.LocalService("workflow")
+ wf_service.trg_validate(uid, 'pos.order', data['id'], 'payment', cr)
return {}
+
class pos_payment(wizard.interface):
states = {
'init': {
- 'actions': [_validate],
+ 'actions': [],
'result': {
'type': 'choice',
'next_state': _check,
@@ -206,8 +182,7 @@ class pos_payment(wizard.interface):
'type': 'form',
'arch': payment_form,
'fields': payment_fields,
- 'state': (('end', 'Cancel'), ('add_pay', 'Ma_ke payment', 'gtk-ok', True)
- )
+ 'state': (('end', 'Cancel'), ('finish', 'Finish'), ('add_pay', 'Ma_ke payment', 'gtk-ok', True))
}
},
'add_pay': {
@@ -222,7 +197,7 @@ class pos_payment(wizard.interface):
'result': {
'type': 'print',
'report': 'pos.invoice',
- 'state': 'end'
+ 'state': 'finish'
}
},
'receipt': {
@@ -230,11 +205,19 @@ class pos_payment(wizard.interface):
'result': {
'type': 'print',
'report': 'pos.receipt',
- 'state': 'end'
+ 'state': 'finish'
}
},
'paid': {
'actions': [],
+ 'result': {
+ 'type': 'print',
+ 'report': 'pos.receipt',
+ 'state': 'finish'
+ }
+ },
+ 'finish': {
+ 'actions': [_trigger_wkf],
'result': {
'type': 'state',
'state': 'end'
diff --git a/addons/point_of_sale/wizard/wizard_pos_payment_report.py b/addons/point_of_sale/wizard/wizard_pos_payment_report.py
new file mode 100644
index 00000000000..1f6ed1afda5
--- /dev/null
+++ b/addons/point_of_sale/wizard/wizard_pos_payment_report.py
@@ -0,0 +1,40 @@
+# -*- encoding: utf-8 -*-
+##############################################################################
+#
+# OpenERP, Open Source Management Solution
+# Copyright (C) 2004-2009 Tiny SPRL (). All Rights Reserved
+# $Id$
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU 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 General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
+#
+##############################################################################
+
+import pooler
+import netsvc
+import wizard
+import time
+
+
+class wizard_pos_payment_report(wizard.interface):
+ states = {
+ 'init': {
+ 'actions': [],
+ 'result': {'type':'print', 'report':'pos.payment.report', 'state':'end'}
+ },
+ }
+
+wizard_pos_payment_report('pos.payment.report')
+
+# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
+
diff --git a/addons/point_of_sale/wizard/wizard_pos_payment_report_date.py b/addons/point_of_sale/wizard/wizard_pos_payment_report_date.py
new file mode 100644
index 00000000000..570b6de9ad7
--- /dev/null
+++ b/addons/point_of_sale/wizard/wizard_pos_payment_report_date.py
@@ -0,0 +1,64 @@
+# -*- encoding: utf-8 -*-
+##############################################################################
+#
+# OpenERP, Open Source Management Solution
+# Copyright (C) 2004-2009 Tiny SPRL (). All Rights Reserved
+# $Id$
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU 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 General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
+#
+##############################################################################
+
+import pooler
+import netsvc
+import wizard
+import time
+
+pos_payment_report_date_form= """
+
+
+
+
+
+"""
+
+pos_payment_report_date_field= {
+
+ 'date_start': {'string':'Start Date','type':'date','required': True,'default': lambda *a: time.strftime('%Y-%m-%d')},
+ 'date_end': {'string':'End Date','type':'date','required': True,'default': lambda *a: time.strftime('%Y-%m-%d')},
+ 'user_id': {'string': 'Salesman', 'type': 'many2many', 'relation': 'res.users', 'required': True},
+}
+
+
+class wizard_pos_payment_report_date(wizard.interface):
+ states = {
+ 'init' : {
+ 'actions' : [],
+ 'result' : {'type' : 'form',
+ 'arch' : pos_payment_report_date_form,
+ 'fields' : pos_payment_report_date_field,
+ 'state' : [('end', 'Cancel','gtk-cancel'),('print_report', 'Print Report','gtk-print') ]}
+ },
+ 'print_report' : {
+ 'actions' : [],
+ 'result' : {'type' : 'print',
+ 'report':'pos.payment.report.date',
+ 'state' : 'end'}
+ },
+ }
+
+wizard_pos_payment_report_date('pos.payment.report.date')
+
+# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
+
diff --git a/addons/point_of_sale/wizard/wizard_pos_payment_report_user.py b/addons/point_of_sale/wizard/wizard_pos_payment_report_user.py
new file mode 100644
index 00000000000..aaad1d328c5
--- /dev/null
+++ b/addons/point_of_sale/wizard/wizard_pos_payment_report_user.py
@@ -0,0 +1,66 @@
+# -*- encoding: utf-8 -*-
+##############################################################################
+#
+# OpenERP, Open Source Management Solution
+# Copyright (C) 2004-2008 Tiny SPRL (). All Rights Reserved
+# $Id$
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU 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 General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
+#
+##############################################################################
+
+from osv import fields
+from osv import osv
+import time
+import ir
+from mx import DateTime
+import datetime
+import pooler
+from tools import config
+import wizard
+import netsvc
+
+
+pos_payment_report_user_form= """
+
+
+
+
+"""
+
+pos_payment_report_user_field= {
+
+ 'user_id': {'string': 'Salesman', 'type': 'many2many', 'relation': 'res.users', 'required': True},
+
+}
+
+
+class wizard_pos_payment_report_user(wizard.interface):
+
+ states = {
+ 'init' : {
+ 'actions' : [],
+ 'result' : {'type' : 'form',
+ 'arch' : pos_payment_report_user_form,
+ 'fields' : pos_payment_report_user_field,
+ 'state' : [('end', 'Cancel','gtk-cancel'),('print_report', 'Print Report','gtk-print') ]}
+ },
+ 'print_report' : {
+ 'actions' : [],
+ 'result' : {'type' : 'print',
+ 'report':'pos.payment.report.user',
+ 'state' : 'end'}
+ },
+ }
+wizard_pos_payment_report_user('pos.payment.report.user')
diff --git a/addons/point_of_sale/wizard/wizard_pos_sales_user.py b/addons/point_of_sale/wizard/wizard_pos_sales_user.py
new file mode 100644
index 00000000000..35b83148bbd
--- /dev/null
+++ b/addons/point_of_sale/wizard/wizard_pos_sales_user.py
@@ -0,0 +1,69 @@
+# -*- encoding: utf-8 -*-
+##############################################################################
+#
+# OpenERP, Open Source Management Solution
+# Copyright (C) 2004-2008 Tiny SPRL (). All Rights Reserved
+# $Id$
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU 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 General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
+#
+##############################################################################
+
+from osv import fields
+from osv import osv
+import time
+import ir
+from mx import DateTime
+import datetime
+import pooler
+from tools import config
+import wizard
+import netsvc
+
+
+sale_forecast_res_form= """
+
+
+
+
+
+
+"""
+
+sale_forecast_res_field= {
+ 'date_start': {'string':'Start Date','type':'date','required': True,'default': lambda *a: time.strftime('%Y-%m-%d')},
+ 'date_end': {'string':'End Date','type':'date','required': True,'default': lambda *a: time.strftime('%Y-%m-%d')},
+ 'user_id': {'string': 'Salesman', 'type': 'many2many', 'relation': 'res.users', 'required': True},
+
+}
+
+
+class wizard_pos_sales_user(wizard.interface):
+
+ states = {
+ 'init' : {
+ 'actions' : [],
+ 'result' : {'type' : 'form',
+ 'arch' : sale_forecast_res_form,
+ 'fields' : sale_forecast_res_field,
+ 'state' : [('end', 'Cancel','gtk-cancel'),('print_report', 'Print Report','gtk-print') ]}
+ },
+ 'print_report' : {
+ 'actions' : [],
+ 'result' : {'type' : 'print',
+ 'report':'pos.sales.user',
+ 'state' : 'end'}
+ },
+ }
+wizard_pos_sales_user('pos.sales.user')
\ No newline at end of file
diff --git a/addons/point_of_sale/wizard/wizard_pos_sales_user_current_user.py b/addons/point_of_sale/wizard/wizard_pos_sales_user_current_user.py
new file mode 100644
index 00000000000..a76c0c97b59
--- /dev/null
+++ b/addons/point_of_sale/wizard/wizard_pos_sales_user_current_user.py
@@ -0,0 +1,40 @@
+# -*- encoding: utf-8 -*-
+##############################################################################
+#
+# OpenERP, Open Source Management Solution
+# Copyright (C) 2004-2009 Tiny SPRL (). All Rights Reserved
+# $Id$
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU 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 General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
+#
+##############################################################################
+
+import pooler
+import netsvc
+import wizard
+import time
+
+
+class wizard_pos_sales_user_today_current_user(wizard.interface):
+ states = {
+ 'init': {
+ 'actions': [],
+ 'result': {'type':'print', 'report':'pos.sales.user.today.current.user', 'state':'end'}
+ },
+ }
+
+wizard_pos_sales_user_today_current_user('pos.sales.user.today.current.user')
+
+# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
+
diff --git a/addons/point_of_sale/wizard/wizard_pos_sales_user_today.py b/addons/point_of_sale/wizard/wizard_pos_sales_user_today.py
new file mode 100644
index 00000000000..58d990ef4bc
--- /dev/null
+++ b/addons/point_of_sale/wizard/wizard_pos_sales_user_today.py
@@ -0,0 +1,66 @@
+# -*- encoding: utf-8 -*-
+##############################################################################
+#
+# OpenERP, Open Source Management Solution
+# Copyright (C) 2004-2008 Tiny SPRL (). All Rights Reserved
+# $Id$
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU 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 General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
+#
+##############################################################################
+
+from osv import fields
+from osv import osv
+import time
+import ir
+from mx import DateTime
+import datetime
+import pooler
+from tools import config
+import wizard
+import netsvc
+
+
+sale_pos_res_form= """
+
+
+
+
+"""
+
+sale_pos_res_field= {
+
+ 'user_id': {'string': 'Salesman', 'type': 'many2many', 'relation': 'res.users', 'required': True},
+
+}
+
+
+class wizard_pos_sales_user_today(wizard.interface):
+
+ states = {
+ 'init' : {
+ 'actions' : [],
+ 'result' : {'type' : 'form',
+ 'arch' : sale_pos_res_form,
+ 'fields' : sale_pos_res_field,
+ 'state' : [('end', 'Cancel','gtk-cancel'),('print_report', 'Print Report','gtk-print') ]}
+ },
+ 'print_report' : {
+ 'actions' : [],
+ 'result' : {'type' : 'print',
+ 'report':'pos.sales.user.today',
+ 'state' : 'end'}
+ },
+ }
+wizard_pos_sales_user_today('pos.sales.user.today')
diff --git a/addons/point_of_sale/wizard/wizard_receipt.py b/addons/point_of_sale/wizard/wizard_receipt.py
new file mode 100644
index 00000000000..64e8a2e5685
--- /dev/null
+++ b/addons/point_of_sale/wizard/wizard_receipt.py
@@ -0,0 +1,49 @@
+# -*- encoding: utf-8 -*-
+##############################################################################
+#
+# OpenERP, Open Source Management Solution
+# Copyright (C) 2004-2009 Tiny SPRL (). All Rights Reserved
+# $Id$
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU 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 General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
+#
+##############################################################################
+
+
+#import time
+#import netsvc
+#from tools.misc import UpdateableStr
+#import pooler
+import wizard
+import pooler
+from tools.translate import _
+
+def _check(self,cr,uid,data,*a):
+ pool = pooler.get_pool(cr.dbname)
+ order_lst = pool.get('pos.order').browse(cr,uid,data['ids'])
+ for order in order_lst:
+ if order.state_2 in ('to_verify'):
+ raise wizard.except_wizard('Error!', 'Can not print the receipt because of discount and/or payment ')
+ return data
+
+class print_order_receipt(wizard.interface):
+ states = {
+ 'init': {
+ 'actions': [_check],
+ 'result': {'type':'print', 'report':'pos.receipt', 'state':'end'}
+ }
+ }
+
+print_order_receipt('ord.receipt')
+
diff --git a/addons/point_of_sale/wizard/wizard_refund_order.py b/addons/point_of_sale/wizard/wizard_refund_order.py
index e20788bccca..188e7b47690 100644
--- a/addons/point_of_sale/wizard/wizard_refund_order.py
+++ b/addons/point_of_sale/wizard/wizard_refund_order.py
@@ -1,93 +1,232 @@
-# -*- coding: utf-8 -*-
+# -*- encoding: utf-8 -*-
##############################################################################
-#
+#
# OpenERP, Open Source Management Solution
-# Copyright (C) 2004-2010 Tiny SPRL ().
+# Copyright (C) 2004-2009 Tiny SPRL (). All Rights Reserved
+# $Id$
#
# 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.
+# it under the terms of the GNU 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.
+# GNU 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 .
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
#
##############################################################################
-#import time
-#import netsvc
-#from tools.misc import UpdateableStr
-#import pooler
+import time
+import netsvc
+from tools.misc import UpdateableStr
import wizard
import pooler
+from mx import DateTime
+from tools.translate import _
-warning_form = '''
-
-
+entry_form = '''
+
+
-
+
+
+
+
+
'''
-warning_fields = {
- 'date_validity': {'string': 'Validity Date', 'type': 'date'}
+def _get_journal(self,cr,uid,context):
+ pool = pooler.get_pool(cr.dbname)
+ obj = pool.get('account.journal')
+ user = pool.get('res.users').browse(cr, uid, uid)
+ ids = obj.search(cr, uid, [('type', '=', 'cash'), ('company_id', '=', user.company_id.id)])
+ res = obj.read(cr, uid, ids, ['id', 'name'], context)
+ res = [(r['id'], r['name']) for r in res]
+ res.insert(0, ('', ''))
+ return res
+
+def _get_pdt(self,cr,uid,context):
+ pool = pooler.get_pool(cr.dbname)
+ obj = pool.get('product.product')
+ ids = obj.search(cr, uid, [('income_pdt', '=', True)])
+ res = obj.read(cr, uid, ids, ['id', 'name'], context)
+ res = [(r['id'], r['name']) for r in res]
+ res.insert(0, ('', ''))
+ return res
+
+def _get_pdt_exp(self,cr,uid,context):
+ pool = pooler.get_pool(cr.dbname)
+ obj = pool.get('product.product')
+ company_id = pool.get('res.users').browse(cr, uid, uid).company_id.id
+ ids = obj.search(cr, uid, ['&', ('expense_pdt', '=', True), '|', ('company_id', '=', company_id), ('company_id', '=', None)])
+ res = obj.read(cr, uid, ids, ['id', 'name'], context)
+ res = [(r['id'], r['name']) for r in res]
+ res.insert(0, ('', ''))
+ return res
+
+entry_fields = {
+ 'journal_id': {'string': 'Journal', 'type': 'selection', 'selection': _get_journal, 'required':True},
+ 'product_id': {'string': 'Operation', 'type': 'selection', 'selection':_get_pdt , 'required':True},
+ 'amount': {'string': 'Amount', 'type': 'float'},
+ 'name': {'string': 'Name', 'type': 'char', 'size': '32', 'required':True},
+ 'ref': {'string': 'Ref.', 'type': 'char', 'size': '32'},
+
}
+out_fields = {
+ 'journal_id': {'string': 'Journal', 'type': 'selection', 'selection': _get_journal, 'required':True},
+ 'product_id': {'string': 'Operation', 'type': 'selection', 'selection':_get_pdt_exp , 'required':True},
+ 'amount': {'string': 'Amount', 'type': 'float'},
+ 'name': {'string': 'Name', 'type': 'char', 'size': '32', 'required':True},
+ 'ref': {'string': 'Ref.', 'type': 'char', 'size': '32'},
+}
-def _get_date(self, cr, uid, data, context):
- order_ref = pooler.get_pool(cr.dbname).get('pos.order')
- order = order_ref.browse(cr, uid, data['id'], context)
- return {'date_validity': order.date_validity}
+def _get_out(self, cr, uid, data, context):
+ args = {}
+ pool = pooler.get_pool(cr.dbname)
+ statement_obj= pool.get('account.bank.statement')
+ product_obj= pool.get('product.template')
+ productp_obj= pool.get('product.product')
+ res_obj = pool.get('res.users')
+ curr_company = res_obj.browse(cr,uid,uid).company_id.id
+ statement_id = statement_obj.search(cr,uid, [('journal_id','=',data['form']['journal_id']),('company_id','=',curr_company),('user_id','=',uid),('state','=','open')])
+ monday = (DateTime.now() + DateTime.RelativeDateTime(weekday=(DateTime.Monday,0))).strftime('%Y-%m-%d')
+ sunday = (DateTime.now() + DateTime.RelativeDateTime(weekday=(DateTime.Sunday,0))).strftime('%Y-%m-%d')
+ done_statmt = statement_obj.search(cr,uid, [('date','>=',monday+' 00:00:00'),('date','<=',sunday+' 23:59:59'),('journal_id','=',data['form']['journal_id']),('company_id','=',curr_company),('user_id','=',uid)])
+ stat_done = statement_obj.browse(cr,uid, done_statmt)
+ address_u = pool.get('res.users').browse(cr,uid,uid).address_id
+ am = 0.0
+ amount_check = productp_obj.browse(cr,uid,data['form']['product_id']).am_out or False
+ for st in stat_done:
+ for s in st.line_ids:
+ if address_u and s.partner_id==address_u.partner_id and s.am_out:
+ am+=s.amount
+ if (-data['form']['amount'] or 0.0)+ am <-(res_obj.browse(cr,uid,uid).company_id.max_diff or 0.0) and amount_check:
+ val = (res_obj.browse(cr,uid,uid).company_id.max_diff or 0.0)+ am
+ raise wizard.except_wizard(_('Error !'), _('The maximum value you can still withdraw is exceeded. \n Remaining value is equal to %d ')%(val))
+ acc_id = product_obj.browse(cr,uid,data['form']['product_id']).property_account_income
+ if not acc_id:
+ raise wizard.except_wizard(_('Error !'), _('please check that account is set to %s')%(product_obj.browse(cr,uid,data['form']['product_id']).name))
+ if not statement_id:
+ raise wizard.except_wizard(_('Error !'), _('You have to open at least one cashbox'))
+ if statement_id:
+ statement_id = statement_id[0]
+ if not statement_id:
+ statement_id = statement_obj.create(cr,uid,{'date':time.strftime('%Y-%m-%d 00:00:00'),
+ 'journal_id':data['form']['journal_id'],
+ 'company_id':curr_company,
+ 'user_id':uid,
+ })
+ args['statement_id']= statement_id
+ args['journal_id']= data['form']['journal_id']
+ if acc_id:
+ args['account_id']= acc_id.id
+ amount= data['form']['amount'] or 0.0
+ if data['form']['amount'] > 0:
+ amount= -data['form']['amount']
+ args['amount'] = amount
+ if productp_obj.browse(cr,uid,data['form']['product_id']).am_out:
+ args['am_out'] = True
+ args['ref'] = data['form']['ref'] or ''
+ args['name'] = "%s: %s "%(product_obj.browse(cr,uid,data['form']['product_id']).name, data['form']['name'].decode('utf8'))
+ address_u = pool.get('res.users').browse(cr,uid,uid).address_id
+ if address_u:
+ partner_id = address_u.partner_id and address_u.partner_id.id or None
+ args['partner_id'] = partner_id
+ statement_line_id = pool.get('account.bank.statement.line').create(cr, uid, args)
+ return {}
-def _refunding(self, cr, uid, data, context):
- order_ref = pooler.get_pool(cr.dbname).get('pos.order')
- clone_list = order_ref.refund(cr, uid, data['ids'], context)
+def _get_in(self, cr, uid, data, context):
+ args = {}
+ pool = pooler.get_pool(cr.dbname)
+ statement_obj = pool.get('account.bank.statement')
+ product_obj = pool.get('product.template')
+ res_obj = pool.get('res.users')
+ curr_company = res_obj.browse(cr,uid,uid).company_id.id
+ statement_id = statement_obj.search(cr,uid, [('journal_id','=',data['form']['journal_id']),('company_id','=',curr_company),('user_id','=',uid),('state','=','open')])
+ if not statement_id:
+ raise wizard.except_wizard(_('Error !'), _('You have to open at least one cashbox'))
- if data['form']['date_validity']:
- order_ref.write(cr, uid, clone_list, {
- 'date_validity': data['form']['date_validity']
- })
+ product = pool.get('product.product').browse(cr, uid, data['form']['product_id'])
+ acc_id = product_obj.browse(cr,uid,data['form']['product_id']).property_account_income
+ if not acc_id:
+ raise wizard.except_wizard(_('Error !'), _('please check that account is set to %s')%(product_obj.browse(cr,uid,data['form']['product_id']).name))
+ if statement_id:
+ statement_id = statement_id[0]
+ if not statement_id:
+ statement_id = statement_obj.create(cr,uid,{'date':time.strftime('%Y-%m-%d 00:00:00'),
+ 'journal_id':data['form']['journal_id'],
+ 'company_id':curr_company,
+ 'user_id':uid,
+ })
- return {
- 'domain': "[('id','in',["+','.join(map(str, clone_list))+"])]",
- 'name': 'Refunded Orders',
- 'view_type': 'form',
- 'view_mode': 'tree,form',
- 'res_model': 'pos.order',
- 'view_id': False,
- #'context': "{'journal_id':%d}" % (form['journal_id'],),
- 'type': 'ir.actions.act_window'
- }
+ args['statement_id'] = statement_id
+ args['journal_id'] = data['form']['journal_id']
+ if acc_id:
+ args['account_id'] = acc_id.id
+ args['amount'] = data['form']['amount'] or 0.0
+ args['ref'] = "%s" %(data['form']['ref'] or '')
+ args['name'] = "%s: %s "% (product_obj.browse(cr,uid,data['form']['product_id']).name, data['form']['name'].decode('utf8'))
+ address_u = pool.get('res.users').browse(cr,uid,uid).address_id
+ if address_u:
+ partner_id = address_u.partner_id and address_u.partner_id.id or None
+ args['partner_id'] = partner_id
+ statement_line_id = pool.get('account.bank.statement.line').create(cr, uid, args)
+ return {}
-class refund_order(wizard.interface):
+class box_entries(wizard.interface):
states = {
'init': {
- 'actions': [_get_date],
+ 'actions': [],
'result': {
'type': 'form',
- 'arch': warning_form,
- 'fields': warning_fields,
- 'state': [('end', 'Cancel', 'gtk-no'), ('refund_n_quit', 'Ok', 'gtk-yes')]
+ 'arch': entry_form % u'Entrée de caisse',
+ 'fields': entry_fields,
+ 'state': [('end', 'Cancel', 'gtk-cancel'), ('next', 'Make entries in the Cashbox', 'gtk-ok')]
}
},
- 'refund_n_quit': {
+ 'next': {
'actions': [],
'result': {
'type': 'action',
- 'action': _refunding,
+ 'action': _get_in,
'state': 'end'
}
},
}
-refund_order('pos.refund_order')
+box_entries('pos.entry')
+
+class box_out(wizard.interface):
+ states = {
+ 'init': {
+ 'actions': [],
+ 'result': {
+ 'type': 'form',
+ 'arch': entry_form % u'Sortie de caisse',
+ 'fields': out_fields,
+ 'state': [('end', 'Cancel', 'gtk-cancel'), ('next', 'Make Entries in the CashBox', 'gtk-ok')]
+ }
+ },
+ 'next': {
+ 'actions': [],
+ 'result': {
+ 'type': 'action',
+ 'action': _get_out,
+ 'state': 'end'
+ }
+ },
+ }
+
+box_out('pos.out')
+# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
diff --git a/addons/point_of_sale/wizard/wizard_return.py b/addons/point_of_sale/wizard/wizard_return.py
new file mode 100644
index 00000000000..591fd00b18a
--- /dev/null
+++ b/addons/point_of_sale/wizard/wizard_return.py
@@ -0,0 +1,546 @@
+# -*- encoding: utf-8 -*-
+##############################################################################
+#
+# OpenERP, Open Source Management Solution
+# Copyright (C) 2004-2009 Tiny SPRL (). All Rights Reserved
+# $Id$
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU 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 General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
+#
+##############################################################################
+
+import wizard
+import pooler
+from tools.misc import UpdateableStr
+
+import netsvc
+import time
+
+from tools.translate import _
+from decimal import Decimal
+
+
+arch=UpdateableStr()
+fields={}
+
+
+def _get_journal(self, cr, uid, context):
+ pool = pooler.get_pool(cr.dbname)
+ obj = pool.get('account.journal')
+ c=pool.get('res.users').browse(cr,uid,uid).company_id.id
+ ids = obj.search(cr, uid, [('type', '=', 'cash'), ('company_id','=',c)])
+ res = obj.read(cr, uid, ids, ['id', 'name'], context)
+ res = [(r['id'], r['name']) for r in res]
+ return res
+
+
+payment_form = """
+
+
+
+
+
+
+
+
+"""
+
+payment_fields = {
+ 'amount': {'string': 'Amount', 'type': 'float', 'required': True},
+ 'invoice_wanted': {'string': 'Invoice', 'type': 'boolean'},
+ 'journal': {'string': 'Journal',
+ 'type': 'selection',
+ 'selection': _get_journal,
+ 'required': True,
+ },
+ 'payment_date': {'string': 'Payment date', 'type': 'date', 'required': True},
+ 'payment_name': {'string': 'Payment name', 'type': 'char', 'size': '32', 'required':True, 'default':'Payment'},
+ 'num_sale': {'string': 'Num.Cof', 'type': 'char', 'size': '32'},
+ }
+
+
+def _pre_init(self, cr, uid, data, context):
+ def _get_journal(pool, order):
+ j_obj = pool.get('account.journal')
+
+ journal_to_fetch = 'DEFAULT'
+ if order.amount_total < 0:
+ journal_to_fetch = 'GIFT'
+ else:
+ if order.amount_paid > 0:
+ journal_to_fetch = 'REBATE'
+
+ pos_config_journal = pool.get('pos.config.journal')
+ ids = pos_config_journal.search(cr, uid, [('code', '=', journal_to_fetch)])
+ objs = pos_config_journal.browse(cr, uid, ids)
+ journal=''
+ if objs:
+ journal = objs[0].journal_id.id
+ else:
+ existing = [payment.journal_id.id for payment in order.payments]
+ ids = j_obj.search(cr, uid, [('type', '=', 'cash')])
+ for i in ids:
+ if i not in existing:
+ journal = i
+ break
+ if not journal:
+ journal = ids and ids[0]
+ return journal
+ pool = pooler.get_pool(cr.dbname)
+ order = pool.get('pos.order').browse(cr, uid, data['id'], context)
+ # get amount to pay:
+# amount = Decimal(str(order.amount_total)) - Decimal(str(order.amount_paid))
+ amount = order.amount_total - order.amount_paid
+ if amount <= 0:
+ pool.get('pos.order').action_paid(cr, uid, data['ids'], context)
+
+ # get journal:
+ journal = _get_journal(pool, order)
+
+ # check if an invoice is wanted:
+ #invoice_wanted_checked = not not order.partner_id # not not -> boolean
+ invoice_wanted_checked = False
+
+ # select the current date
+ current_date = time.strftime('%Y-%m-%d')
+
+ return {'journal': journal, 'amount': amount, 'invoice_wanted': invoice_wanted_checked, 'payment_date': current_date}
+
+
+def _add_pay(self, cr, uid, data, context):
+ pool = pooler.get_pool(cr.dbname)
+ order_obj = pool.get('pos.order')
+ jrnl_obj = pool.get('account.journal')
+ result = data['form']
+ invoice_wanted = data['form']['invoice_wanted']
+ jrnl_used=False
+ if data['form'] and data['form'].get('journal',False):
+ jrnl_used=jrnl_obj.browse(cr,uid,data['form']['journal'])
+
+ # add 'invoice_wanted' in 'pos.order'
+ order_obj.write(cr, uid, [data['id']], {'invoice_wanted': invoice_wanted})
+
+ order_obj.add_payment(cr, uid, data['id'], result, context=context)
+ return {}
+
+
+def _check(self, cr, uid, data, context):
+ """Check the order:
+ if the order is not paid: continue payment,
+ if the order is paid print invoice (if wanted) or ticket.
+ """
+ pool = pooler.get_pool(cr.dbname)
+ order_obj = pool.get('pos.order')
+ order = order_obj.browse(cr, uid, data['id'], context)
+ order_obj.test_order_lines(cr, uid, order, context=context)
+
+ action = 'ask_pay'
+ if order.state == 'paid':
+ if order.partner_id:
+ if order.invoice_wanted:
+ action = 'invoice'
+ else:
+ action = 'paid'
+ elif order.date_payment:
+ action = 'receipt'
+ else:
+ action='paid'
+
+ if order.amount_total == order.amount_paid:
+ order_obj.write(cr,uid,data['ids'],{'state':'done'})
+ action = 'receipt'
+
+ return action
+
+
+def create_invoice(self, cr, uid, data, context):
+ wf_service = netsvc.LocalService("workflow")
+ for i in data['ids']:
+ wf_service.trg_validate(uid, 'pos.order', i, 'invoice', cr)
+ return {}
+
+
+
+_form = """
+
' % _('Return lines'), '' % _('Quantities you enter, match to products that will return to the stock.')]
+ for m in [line for line in order.lines]:
+ quantity=m.qty
+ arch_lst.append('\n' % (m.id,))
+ fields['return%s' % m.id]={'string':m.product_id.name, 'type':'float', 'required':True, 'default':quantity}
+ res.setdefault('returns', []).append(m.id)
+ arch_lst.append('
')
+ arch.string='\n'.join(arch_lst)
+ return res
+
+def _create_returns(self, cr, uid, data, context):
+ pool = pooler.get_pool(cr.dbname)
+ order_obj = pool.get('pos.order')
+ lines_obj = pool.get('pos.order.line')
+ picking_obj = pool.get('stock.picking')
+ stock_move_obj = pool.get('stock.move')
+ move_obj = pool.get('stock.move')
+ picking_ids = picking_obj.search(cr, uid, [('pos_order', 'in', data['ids']), ('state', '=', 'done')])
+ clone_list = []
+ date_cur=time.strftime('%Y-%m-%d')
+ uom_obj = pool.get('product.uom')
+ wf_service = netsvc.LocalService("workflow")
+ for order_id in order_obj.browse(cr, uid, data['ids'], context=context):
+ prop_ids = pool.get("ir.property").search(cr, uid,[('name', '=', 'property_stock_customer')])
+ val = pool.get("ir.property").browse(cr, uid,prop_ids[0]).value
+ cr.execute("select s.id from stock_location s, stock_warehouse w where w.lot_stock_id=s.id and w.id= %d "%(order_id.shop_id.warehouse_id.id))
+ res=cr.fetchone()
+ location_id=res and res[0] or None
+ stock_dest_id = int(val.split(',')[1])
+
+ order_obj.write(cr,uid,[order_id.id],{'type_rec':'Exchange'})
+ if order_id.invoice_id:
+ pool.get('account.invoice').refund(cr, uid, [order_id.invoice_id.id],time.strftime('%Y-%m-%d'), False, order_id.name)
+ new_picking=picking_obj.create(cr,uid,{
+ 'name':'%s (return)' %order_id.name,
+ 'move_lines':[], 'state':'draft',
+ 'type':'in',
+ 'date':date_cur, })
+ for line in order_id.lines:
+ for r in data['form'].get('returns',[]):
+ if line.id==r and (data['form']['return%s' %r]!=0.0):
+ new_move=stock_move_obj.create(cr, uid,{
+ 'product_qty': data['form']['return%s' %r],
+ 'product_uos_qty': uom_obj._compute_qty(cr, uid,data['form']['return%s' %r] ,line.product_id.uom_id.id),
+ 'picking_id':new_picking,
+ 'product_uom':line.product_id.uom_id.id,
+ 'location_id':location_id,
+ 'product_id':line.product_id.id,
+ 'location_dest_id':stock_dest_id,
+ 'name':'%s (return)' %order_id.name,
+ 'date':date_cur,
+ 'date_planned':date_cur,})
+ lines_obj.write(cr,uid,[line.id],{'qty_rfd':(line.qty or 0.0) + data['form']['return%s' %r],
+ 'qty':line.qty-(data['form']['return%s' %r] or 0.0)
+ })
+ wf_service.trg_validate(uid, 'stock.picking',new_picking,'button_confirm', cr)
+ picking_obj.force_assign(cr, uid, [new_picking], context)
+ return res
+
+def _create_returns2(self, cr, uid, data, context):
+ pool = pooler.get_pool(cr.dbname)
+ order_obj = pool.get('pos.order')
+ line_obj = pool.get('pos.order.line')
+ picking_obj = pool.get('stock.picking')
+ stock_move_obj = pool.get('stock.move')
+ picking_ids = picking_obj.search(cr, uid, [('pos_order', 'in', data['ids']), ('state', '=', 'done')])
+ clone_list = []
+ date_cur=time.strftime('%Y-%m-%d')
+ uom_obj = pool.get('product.uom')
+ wf_service = netsvc.LocalService("workflow")
+ for order_id in order_obj.browse(cr, uid, data['ids'], context=context):
+ prop_ids = pool.get("ir.property").search(cr, uid,[('name', '=', 'property_stock_customer')])
+ val = pool.get("ir.property").browse(cr, uid,prop_ids[0]).value
+ cr.execute("select s.id from stock_location s, stock_warehouse w where w.lot_stock_id=s.id and w.id= %d "%(order_id.shop_id.warehouse_id.id))
+ res=cr.fetchone()
+ location_id=res and res[0] or None
+ stock_dest_id = int(val.split(',')[1])
+
+ new_picking=picking_obj.copy(cr, uid, order_id.last_out_picking.id, {'name':'%s (return)' % order_id.name,
+ 'move_lines':[], 'state':'draft', 'type':'in',
+ 'type':'in',
+ 'date':date_cur, })
+ new_order=order_obj.copy(cr,uid,order_id.id, {'name': 'Refund %s'%order_id.name,
+ 'lines':[],
+ 'statement_ids':[],
+ 'last_out_picking':[]})
+ for line in order_id.lines:
+ for r in data['form'].get('returns',[]):
+ if line.id==r and (data['form']['return%s' %r]!=0.0):
+ new_move=stock_move_obj.create(cr, uid,{
+ 'product_qty': data['form']['return%s' %r],
+ 'product_uos_qty': uom_obj._compute_qty(cr, uid,data['form']['return%s' %r] ,line.product_id.uom_id.id),
+ 'picking_id':new_picking,
+ 'product_uom':line.product_id.uom_id.id,
+ 'location_id':location_id,
+ 'product_id':line.product_id.id,
+ 'location_dest_id':stock_dest_id,
+ 'name':'%s (return)' %order_id.name,
+ 'date':date_cur,
+ 'date_planned':date_cur,})
+ line_obj.copy(cr,uid,line.id,{'qty':-data['form']['return%s' %r],
+ 'order_id': new_order,
+ })
+ order_obj.write(cr,uid, new_order, {'state':'done'})
+ wf_service.trg_validate(uid, 'stock.picking',new_picking,'button_confirm', cr)
+ picking_obj.force_assign(cr, uid, [new_picking], context)
+ act = {
+ 'domain': "[('id', 'in', ["+str(new_order)+"])]",
+ 'name': 'Refunded Orders',
+ 'view_type': 'form',
+ 'view_mode': 'form,tree',
+ 'res_model': 'pos.order',
+ 'auto_refresh':0,
+ 'res_id':new_order,
+ 'view_id': False,
+ 'type': 'ir.actions.act_window'
+ }
+ return act
+def test(self,cr,uid,data,context={}):
+ # import pdb; pdb.set_trace()
+ data['id']=data['res_id']
+ return {'id':data['res_id']}
+
+#def _raise(self,cr,uid,data,context={}):
+# return datas
+# raise wizard.except_wizard(_('Message'),_('You can not exchange products more than total paid amount.'))
+
+
+#def _test_exist1(self,cr,uid,data,context={}):
+# return 'choice'
+
+def _test_exist(self,cr,uid,data,context={}):
+# order_obj= pooler.get_pool(cr.dbname).get('pos.order')
+# order_line_obj= pooler.get_pool(cr.dbname).get('pos.order.line')
+# obj=order_obj.browse(cr,uid, data['ids'])[0]
+# am_tot=obj._amount_total(cr, uid, data['ids'])
+# order_obj.write(cr,uid,data['ids'],{'state':'done'})
+# if obj.amount_total == obj.amount_paid:
+# return 'receipt'
+# elif obj.amount_total > obj.amount_paid:
+# sql = """select max(id) from pos_order_line where order_id = %d """%(obj.id)
+# cr.execute(sql)
+# res = cr.fetchone()
+# cr.execute("delete from pos_order_line where id = %d"%(res[0]))
+# cr.commit()
+# return 'choice_raise'
+# else:
+ return 'add_p'
+
+def _close(self,cr,uid,data,context={}):
+ order_obj= pooler.get_pool(cr.dbname).get('pos.order')
+ order_line_obj= pooler.get_pool(cr.dbname).get('pos.order.line')
+ obj=order_obj.browse(cr,uid, data['ids'])[0]
+ order_obj.write(cr,uid,data['ids'],{'state':'done'})
+ if obj.amount_total != obj.amount_paid:
+ return 'ask_pay'
+ else :
+ return 'receipt'
+
+
+
+
+def _add_pdct(self, cr, uid, data, context):
+ pool = pooler.get_pool(cr.dbname)
+ order_obj = pool.get('pos.order')
+ line_obj = pool.get('pos.order.line')
+ picking_obj = pool.get('stock.picking')
+ wf_service = netsvc.LocalService("workflow")
+ prod_obj = pool.get('product.product')
+ stock_move_obj = pool.get('stock.move')
+ uom_obj = pool.get('product.uom')
+ date_cur=time.strftime('%Y-%m-%d')
+ order_obj.add_product(cr, uid, data['id'], data['form']['product'],
+ data['form']['quantity'], context=context)
+ cr.commit()
+ for order_id in order_obj.browse(cr, uid, data['ids'], context=context):
+ prod=data['form']['product']
+ qty=data['form']['quantity']
+ prop_ids = pool.get("ir.property").search(cr, uid,[('name', '=', 'property_stock_customer')])
+ val = pool.get("ir.property").browse(cr, uid,prop_ids[0]).value
+ cr.execute("select s.id from stock_location s, stock_warehouse w where w.lot_stock_id=s.id and w.id= %d "%(order_id.shop_id.warehouse_id.id))
+ res=cr.fetchone()
+ location_id=res and res[0] or None
+ stock_dest_id = int(val.split(',')[1])
+
+ prod_id=prod_obj.browse(cr,uid,prod)
+ new_picking=picking_obj.create(cr,uid,{
+ 'name':'%s (Added)' %order_id.name,
+ 'move_lines':[],
+ 'state':'draft',
+ 'type':'out',
+ 'date':date_cur, })
+ new_move=stock_move_obj.create(cr, uid,{
+ 'product_qty': qty,
+ 'product_uos_qty': uom_obj._compute_qty(cr, uid,prod_id.uom_id.id, qty, prod_id.uom_id.id),
+ 'picking_id':new_picking,
+ 'product_uom':prod_id.uom_id.id,
+ 'location_id':location_id,
+ 'product_id':prod_id.id,
+ 'location_dest_id':stock_dest_id,
+ 'name':'%s (return)' %order_id.name,
+ 'date':date_cur,
+ 'date_planned':date_cur,})
+
+ wf_service.trg_validate(uid, 'stock.picking',new_picking,'button_confirm', cr)
+ picking_obj.force_assign(cr, uid, [new_picking], context)
+ # order_obj.write(cr,uid,data['id'],{'state':'done','last_out_picking':new_picking})
+ order_obj.write(cr,uid,data['id'],{'last_out_picking':new_picking})
+ return {}
+
+
+
+
+class wizard_return_picking(wizard.interface):
+ states={
+ 'init':{
+ 'actions':[_get_returns],
+ 'result':{'type':'form',
+ 'arch':arch,
+ 'fields':fields,
+ 'state':[('end','Cancel', 'gtk-cancel'),('return','Return goods and Exchange', 'gtk-ok'),('return_w','Return without Refund','gtk-ok')]
+ }
+ },
+ 'return':{
+ 'actions':[],
+ 'result':{ 'type': 'action',
+ 'action' : _create_returns,
+ 'state':'prod'}
+ },
+ 'prod':{
+ 'actions':[],
+ 'result': {
+ 'type': 'form',
+ 'arch': _form,
+ 'fields':_fields,
+ 'state': [('close','Close'),('choice','Continue')]
+ }
+ },
+# 'choice1' : {
+# 'actions' : [_add_pdct],
+# 'result' : {'type' : 'choice', 'next_state': _test_exist1 }
+# },
+ 'choice' : {
+ 'actions' : [],
+ 'result' : {'type' : 'choice', 'next_state': _test_exist }
+ },
+# 'choice_raise':{
+# 'actions':[],
+# 'result':{ 'type': 'action',
+# 'action' : _raise,
+# 'state':'end'}
+# },
+ 'add_p' :{
+ 'actions':[],
+ 'result':{
+ 'type':'action',
+ 'action': _add_pdct,
+ 'state': 'prod'}
+ },
+# 'add_pp' :{
+# 'actions':[],
+# 'result':{
+# 'type':'action',
+# 'action': _add_pdct,
+# 'state': 'end'}
+# },
+ 'receipt':{
+ 'result': {
+ 'type': 'print',
+ 'report': 'pos.receipt',
+ 'state': 'end'
+ }
+ },
+ 'return_w':{
+ 'actions':[],
+ 'result':{'type':'action', 'action':_create_returns2, 'state':'end'}
+ },
+
+ 'close':{
+ 'actions' : [],
+ 'result' : {'type' : 'choice', 'next_state': _close }
+ },
+
+ 'check': {
+ 'actions': [],
+ 'result': {
+ 'type': 'choice',
+ 'next_state': _check,
+ }
+ },
+
+ 'ask_pay': {
+ 'actions': [_pre_init],
+ 'result': {
+ 'type': 'form',
+ 'arch': payment_form,
+ 'fields': payment_fields,
+ 'state': (('end', 'Cancel'), ('add_pay', 'Ma_ke payment', 'gtk-ok', True)
+ )
+ }
+ },
+ 'add_pay': {
+ 'actions': [_add_pay],
+ 'result': {
+ 'type': 'state',
+ 'state': "check",
+ }
+ },
+
+
+ 'invoice': {
+ 'actions': [create_invoice],
+ 'result': {
+ 'type': 'print',
+ 'report': 'pos.invoice',
+ 'state': 'end'
+ }
+ },
+ 'receipt': {
+ 'actions': [],
+ 'result': {
+ 'type': 'print',
+ 'report': 'pos.receipt',
+ 'state': 'end'
+ }
+ },
+ 'paid': {
+ 'actions': [],
+ 'result': {
+ 'type': 'state',
+ 'state': 'end'
+ }
+ },
+
+ }
+wizard_return_picking('pos.return.picking')
+
+# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
diff --git a/addons/point_of_sale/wizard/wizard_scan_product.py b/addons/point_of_sale/wizard/wizard_scan_product.py
index 64180a626a2..40a8a5b1246 100644
--- a/addons/point_of_sale/wizard/wizard_scan_product.py
+++ b/addons/point_of_sale/wizard/wizard_scan_product.py
@@ -2,7 +2,7 @@
##############################################################################
#
# OpenERP, Open Source Management Solution
-# Copyright (C) 2004-2010 Tiny SPRL (). All Rights Reserved
+# Copyright (C) 2004-2009 Tiny SPRL (). All Rights Reserved
# Copyright (c) 2008 Sylëam Info Services. (http://www.syleam.fr) All Rights Reserved.
#
# This program is free software: you can redistribute it and/or modify
diff --git a/addons/project/project_view.xml b/addons/project/project_view.xml
index cee6d9ac2e2..b0f7ca4df52 100644
--- a/addons/project/project_view.xml
+++ b/addons/project/project_view.xml
@@ -151,14 +151,14 @@
- All projects
+ Projectsproject.projectform[]
-
+ Templates of Projects
@@ -503,7 +503,7 @@
-
+ Overpassed Tasks
diff --git a/addons/project_long_term/project_view.xml b/addons/project_long_term/project_view.xml
index eb968e38312..b2219f8f281 100644
--- a/addons/project_long_term/project_view.xml
+++ b/addons/project_long_term/project_view.xml
@@ -92,10 +92,9 @@
res_model="project.task"
src_model="project.phase"
view_mode="tree,form"
- domain="[('phase_id','=',active_id)]"/>
-
-
-
+ domain="[('phase_id','=',active_id)]"/>
+
+
diff --git a/addons/purchase_tender/__init__.py b/addons/purchase_tender/__init__.py
new file mode 100644
index 00000000000..68f1f7ae5bc
--- /dev/null
+++ b/addons/purchase_tender/__init__.py
@@ -0,0 +1,22 @@
+##############################################################################
+#
+# OpenERP, Open Source Management Solution
+# Copyright (C) 2004-2009 Tiny SPRL ().
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as
+# published by the Free Software Foundation, either version 3 of the
+# License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see .
+#
+##############################################################################
+import purchase_tender
+# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
+
diff --git a/addons/purchase_tender/__terp__.py b/addons/purchase_tender/__terp__.py
new file mode 100644
index 00000000000..723ec148162
--- /dev/null
+++ b/addons/purchase_tender/__terp__.py
@@ -0,0 +1,37 @@
+##############################################################################
+#
+# OpenERP, Open Source Management Solution
+# Copyright (C) 2004-2009 Tiny SPRL ().
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as
+# published by the Free Software Foundation, either version 3 of the
+# License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see .
+#
+##############################################################################
+{
+ "name" : "Purchase - Purchase Tender",
+ "version" : "0.1",
+ "author" : "Tiny",
+ "category" : "Generic Modules/Purchase",
+ "website" : "http://www.openerp.com",
+ "description": """ This module allows you to manage your Purchase Tenders. When a purchase order is created, you now have the opportunity to save the related tender.
+ This new object will regroup and will allow you to easily keep track and order all your purchase orders.
+""",
+ "depends" : ["purchase"],
+ "init_xml" : [],
+ "demo_xml" : [],
+ "update_xml" : ["purchase_tender_view.xml","purchase_tender_sequence.xml"],
+ "active": False,
+ "installable": True
+}
+# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
+
diff --git a/addons/purchase_tender/i18n/fr_BE.po b/addons/purchase_tender/i18n/fr_BE.po
new file mode 100644
index 00000000000..5b9c10ca2cb
--- /dev/null
+++ b/addons/purchase_tender/i18n/fr_BE.po
@@ -0,0 +1,134 @@
+# Translation of OpenERP Server.
+# This file contains the translation of the following modules:
+# * purchase_tender
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: OpenERP Server 5.0.6\n"
+"Report-Msgid-Bugs-To: support@openerp.com\n"
+"POT-Creation-Date: 2009-11-25 14:07:40+0000\n"
+"PO-Revision-Date: 2009-11-25 14:07:40+0000\n"
+"Last-Translator: <>\n"
+"Language-Team: \n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: \n"
+"Plural-Forms: \n"
+
+#. module: purchase_tender
+#: constraint:ir.ui.view:0
+msgid "Invalid XML for View Architecture!"
+msgstr "XML incorrect pour l'Architecture des Vues!"
+
+#. module: purchase_tender
+#: field:purchase.tender,date_end:0
+msgid "Date End"
+msgstr "Date de fin"
+
+#. module: purchase_tender
+#: constraint:ir.model:0
+msgid "The Object name must start with x_ and not contain any special character !"
+msgstr "Le nom de l'Objet doit commencer par x_ et ne pas comporter de caractères spéciaux !"
+
+#. module: purchase_tender
+#: view:purchase.tender:0
+#: field:purchase.tender,description:0
+msgid "Description"
+msgstr "Description"
+
+#. module: purchase_tender
+#: model:ir.model,name:purchase_tender.model_purchase_tender
+#: field:purchase.order,tender_id:0
+#: view:purchase.tender:0
+msgid "Purchase Tender"
+msgstr "Appel d'Offre"
+
+#. module: purchase_tender
+#: model:ir.actions.act_window,name:purchase_tender.action_purchase_tender
+#: model:ir.ui.menu,name:purchase_tender.menu_purchase_Tender1
+#: model:ir.ui.menu,name:purchase_tender.menu_purchase_tender
+msgid "Purchase Tenders"
+msgstr "Appels d'offre"
+
+#. module: purchase_tender
+#: selection:purchase.tender,state:0
+msgid "Open"
+msgstr "Ouvert"
+
+#. module: purchase_tender
+#: field:purchase.tender,user_id:0
+msgid "Responsible"
+msgstr "Responsable"
+
+#. module: purchase_tender
+#: model:ir.actions.act_window,name:purchase_tender.action_purchase_tender_draft
+#: model:ir.ui.menu,name:purchase_tender.menu_purchase_Tender1_draft
+msgid "Draft Purchase Tenders"
+msgstr "Appels d'Offre brouillons"
+
+#. module: purchase_tender
+#: field:purchase.tender,state:0
+msgid "State"
+msgstr "Etat"
+
+#. module: purchase_tender
+#: selection:purchase.tender,state:0
+msgid "Draft"
+msgstr "Brouillon"
+
+#. module: purchase_tender
+#: model:ir.actions.act_window,name:purchase_tender.action_purchase_tender_open
+#: model:ir.ui.menu,name:purchase_tender.menu_purchase_Tender1_open
+msgid "Open Purchase Tenders"
+msgstr "Appels d'offre ouverts"
+
+#. module: purchase_tender
+#: constraint:ir.actions.act_window:0
+msgid "Invalid model name in the action definition."
+msgstr "Nom de modèle incorrect pour la définition de l'action"
+
+#. module: purchase_tender
+#: model:ir.module.module,shortdesc:purchase_tender.module_meta_information
+msgid "Purchase - Purchase Tender"
+msgstr "Achat - Appel d'offre"
+
+#. module: purchase_tender
+#: field:purchase.tender,name:0
+msgid "Tender Reference"
+msgstr "Référence"
+
+#. module: purchase_tender
+#: selection:purchase.tender,state:0
+msgid "Close"
+msgstr "Clôturé"
+
+#. module: purchase_tender
+#: field:purchase.tender,date_start:0
+msgid "Date Start"
+msgstr "Date de début"
+
+#. module: purchase_tender
+#: view:purchase.tender:0
+msgid "Quotations"
+msgstr ""
+
+#. module: purchase_tender
+#: model:ir.module.module,description:purchase_tender.module_meta_information
+msgid " This module allows you to manage your Purchase Tenders. When a purchase order is created, you now have the opportunity to save the related tender. \n"
+" This new object will regroup and will allow you to easily keep track and order all your purchase orders.\n"
+""
+msgstr "Ce module vous permet de gérer des appels d'offre. Quand un appel d'offre est créé, vous avez maintenant l'opportunité de conserver une trace. \n"
+" Ce nouvel objet regroupe et conserve la trace de tous vos appels d'offre.\n"
+""
+
+#. module: purchase_tender
+#: model:ir.actions.act_window,name:purchase_tender.action_purchase_tender_new
+#: model:ir.ui.menu,name:purchase_tender.menu_purchase_Tender1_new
+msgid "New Purchase Tenders"
+msgstr "Nouveaux Appels d'Offre"
+
+#. module: purchase_tender
+#: field:purchase.tender,purchase_ids:0
+msgid "Purchase Orders"
+msgstr "Bons d'achat"
+
diff --git a/addons/purchase_tender/purchase_tender.py b/addons/purchase_tender/purchase_tender.py
new file mode 100644
index 00000000000..d68281f3a6f
--- /dev/null
+++ b/addons/purchase_tender/purchase_tender.py
@@ -0,0 +1,63 @@
+# -*- encoding: utf-8 -*-
+##############################################################################
+#
+# OpenERP, Open Source Management Solution
+# Copyright (C) 2004-2008 Tiny SPRL (). All Rights Reserved
+# $Id$
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU 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 General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
+#
+##############################################################################
+
+from osv import fields,osv
+from osv import orm
+import netsvc
+import time
+
+class purchase_tender(osv.osv):
+ _name = "purchase.tender"
+ _description="Purchase Tender"
+ _columns = {
+ 'name': fields.char('Tender Reference', size=32,required=True),
+ 'date_start': fields.datetime('Date Start'),
+ 'date_end': fields.datetime('Date End'),
+ 'user_id': fields.many2one('res.users', 'Responsible'),
+ 'description': fields.text('Description'),
+ 'purchase_ids' : fields.one2many('purchase.order','tender_id','Purchase Orders'),
+ 'state': fields.selection([('draft','Draft'),('open','Open'),('close','Close')], 'State', required=True)
+ }
+ _defaults = {
+ 'date_start': lambda *args: time.strftime('%Y-%m-%d %H:%M:%S'),
+ 'state': lambda *args: 'open',
+ 'name': lambda obj, cr, uid, context: obj.pool.get('ir.sequence').get(cr, uid, 'purchase.order.tender'),
+ }
+purchase_tender()
+
+class purchase_order(osv.osv):
+ _inherit = "purchase.order"
+ _description = "purchase order"
+ _columns = {
+ 'tender_id' : fields.many2one('purchase.tender','Purchase Tender')
+ }
+ def wkf_confirm_order(self, cr, uid, ids, context={}):
+ res = super(purchase_order, self).wkf_confirm_order(cr, uid, ids, context)
+ for po in self.browse(cr, uid, ids, context):
+ if po.tender_id:
+ for order in po.tender_id.purchase_ids:
+ if order.id<>po.id:
+ wf_service = netsvc.LocalService("workflow")
+ wf_service.trg_validate(uid, 'purchase.order', order.id, 'purchase_cancel', cr)
+ self.pool.get('purchase.tender').write(cr, uid, [po.tender_id.id], {'state':'close'})
+ return res
+purchase_order()
diff --git a/addons/purchase_tender/purchase_tender_sequence.xml b/addons/purchase_tender/purchase_tender_sequence.xml
new file mode 100644
index 00000000000..222e3f46282
--- /dev/null
+++ b/addons/purchase_tender/purchase_tender_sequence.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+ Purchase Tender Order
+ purchase.order.tender
+
+
+ Purchase Tender Order
+ purchase.order.tender
+ TE
+ 5
+
+
+
diff --git a/addons/purchase_tender/purchase_tender_view.xml b/addons/purchase_tender/purchase_tender_view.xml
new file mode 100644
index 00000000000..a91c36a7201
--- /dev/null
+++ b/addons/purchase_tender/purchase_tender_view.xml
@@ -0,0 +1,102 @@
+
+
+
+
+
+ purchase.order.tree.inherit
+ tree
+ purchase.order
+
+
+
+
+
+
+
+
+
+ purchase.order.form.inherit
+ form
+ purchase.order
+
+
+
+
+
+
+
+
+
+ purchase.tender.form
+ form
+ purchase.tender
+
+