def __new__(cls, name, bases, nmspc):

        columns = nmspc['_columns']
        size = int(config.get_misc('analytic', 'analytic_size', 5))
        for n in xrange(1, size + 1):
            columns['ns{}_id'.format(n)] = fields.one2many(
                'analytic.structure',
                'nd_id',
                "Generated Subset of Structures",
                domain=[('ordering', '=', n)],
                auto_join=True,
            )
        return super(_dimension_meta, cls).__new__(cls, name, bases, nmspc)
Exemplo n.º 2
0
class module(osv.osv):
    _name = "ir.module.module"
    _rec_name = "shortdesc"
    _description = "Module"

    def fields_view_get(self,
                        cr,
                        uid,
                        view_id=None,
                        view_type='form',
                        context=None,
                        toolbar=False,
                        submenu=False):
        res = super(module, self).fields_view_get(cr,
                                                  uid,
                                                  view_id=view_id,
                                                  view_type=view_type,
                                                  context=context,
                                                  toolbar=toolbar,
                                                  submenu=False)
        result = self.pool.get('ir.model.data').get_object_reference(
            cr, uid, 'base', 'action_server_module_immediate_install')[1]
        if view_type == 'form':
            if res.get('toolbar', False):
                list = [
                    rec for rec in res['toolbar']['action']
                    if rec.get('id', False) != result
                ]
                res['toolbar'] = {'action': list}
        return res

    @classmethod
    def get_module_info(cls, name):
        info = {}
        try:
            info = modules.load_information_from_description_file(name)
        except Exception:
            _logger.debug(
                'Error when trying to fetch informations for '
                'module %s',
                name,
                exc_info=True)
        return info

    def _get_desc(self, cr, uid, ids, field_name=None, arg=None, context=None):
        res = dict.fromkeys(ids, '')
        for module in self.browse(cr, uid, ids, context=context):
            path = get_module_resource(module.name,
                                       'static/description/index.html')
            if path:
                with tools.file_open(path, 'rb') as desc_file:
                    doc = desc_file.read()
                    html = lxml.html.document_fromstring(doc)
                    for element, attribute, link, pos in html.iterlinks():
                        if element.get('src') and not '//' in element.get(
                                'src') and not 'static/' in element.get('src'):
                            element.set(
                                'src', "/%s/static/description/%s" %
                                (module.name, element.get('src')))
                    res[module.id] = lxml.html.tostring(html)
            else:
                overrides = {
                    'embed_stylesheet': False,
                    'doctitle_xform': False,
                    'output_encoding': 'unicode',
                    'xml_declaration': False,
                }
                output = publish_string(source=module.description or '',
                                        settings_overrides=overrides,
                                        writer=MyWriter())
                res[module.id] = output
        return res

    def _get_latest_version(self,
                            cr,
                            uid,
                            ids,
                            field_name=None,
                            arg=None,
                            context=None):
        default_version = modules.adapt_version('1.0')
        res = dict.fromkeys(ids, default_version)
        for m in self.browse(cr, uid, ids):
            res[m.id] = self.get_module_info(m.name).get(
                'version', default_version)
        return res

    def _get_views(self,
                   cr,
                   uid,
                   ids,
                   field_name=None,
                   arg=None,
                   context=None):
        res = {}
        model_data_obj = self.pool.get('ir.model.data')

        dmodels = []
        if field_name is None or 'views_by_module' in field_name:
            dmodels.append('ir.ui.view')
        if field_name is None or 'reports_by_module' in field_name:
            dmodels.append('ir.actions.report.xml')
        if field_name is None or 'menus_by_module' in field_name:
            dmodels.append('ir.ui.menu')
        assert dmodels, "no models for %s" % field_name

        for module_rec in self.browse(cr, uid, ids, context=context):
            res_mod_dic = res[module_rec.id] = {
                'menus_by_module': [],
                'reports_by_module': [],
                'views_by_module': []
            }

            # Skip uninstalled modules below, no data to find anyway.
            if module_rec.state not in ('installed', 'to upgrade',
                                        'to remove'):
                continue

            # then, search and group ir.model.data records
            imd_models = dict([(m, []) for m in dmodels])
            imd_ids = model_data_obj.search(cr, uid,
                                            [('module', '=', module_rec.name),
                                             ('model', 'in', tuple(dmodels))])

            for imd_res in model_data_obj.read(cr,
                                               uid,
                                               imd_ids, ['model', 'res_id'],
                                               context=context):
                imd_models[imd_res['model']].append(imd_res['res_id'])

            def browse(model):
                M = self.pool[model]
                # as this method is called before the module update, some xmlid may be invalid at this stage
                # explictly filter records before reading them
                ids = M.exists(cr, uid, imd_models.get(model, []), context)
                return M.browse(cr, uid, ids, context)

            def format_view(v):
                aa = v.inherit_id and '* INHERIT ' or ''
                return '%s%s (%s)' % (aa, v.name, v.type)

            res_mod_dic['views_by_module'] = map(format_view,
                                                 browse('ir.ui.view'))
            res_mod_dic['reports_by_module'] = map(
                attrgetter('name'), browse('ir.actions.report.xml'))
            res_mod_dic['menus_by_module'] = map(attrgetter('complete_name'),
                                                 browse('ir.ui.menu'))

        for key in res.iterkeys():
            for k, v in res[key].iteritems():
                res[key][k] = "\n".join(sorted(v))
        return res

    def _get_icon_image(self,
                        cr,
                        uid,
                        ids,
                        field_name=None,
                        arg=None,
                        context=None):
        res = dict.fromkeys(ids, '')
        for module in self.browse(cr, uid, ids, context=context):
            path = get_module_resource(module.name, 'static', 'description',
                                       'icon.png')
            if path:
                image_file = tools.file_open(path, 'rb')
                try:
                    res[module.id] = image_file.read().encode('base64')
                finally:
                    image_file.close()
        return res

    _columns = {
        'name':
        fields.char("Technical Name",
                    readonly=True,
                    required=True,
                    select=True),
        'category_id':
        fields.many2one('ir.module.category',
                        'Category',
                        readonly=True,
                        select=True),
        'shortdesc':
        fields.char('Module Name', readonly=True, translate=True),
        'summary':
        fields.char('Summary', readonly=True, translate=True),
        'description':
        fields.text("Description", readonly=True, translate=True),
        'description_html':
        fields.function(_get_desc,
                        string='Description HTML',
                        type='html',
                        method=True,
                        readonly=True),
        'author':
        fields.char("Author", readonly=True),
        'maintainer':
        fields.char('Maintainer', readonly=True),
        'contributors':
        fields.text('Contributors', readonly=True),
        'website':
        fields.char("Website", readonly=True),

        # attention: Incorrect field names !!
        #   installed_version refers the latest version (the one on disk)
        #   latest_version refers the installed version (the one in database)
        #   published_version refers the version available on the repository
        'installed_version':
        fields.function(_get_latest_version,
                        string='Latest Version',
                        type='char'),
        'latest_version':
        fields.char('Installed Version', readonly=True),
        'published_version':
        fields.char('Published Version', readonly=True),
        'url':
        fields.char('URL', readonly=True),
        'sequence':
        fields.integer('Sequence'),
        'dependencies_id':
        fields.one2many('ir.module.module.dependency',
                        'module_id',
                        'Dependencies',
                        readonly=True),
        'auto_install':
        fields.boolean(
            'Automatic Installation',
            help='An auto-installable module is automatically installed by the '
            'system when all its dependencies are satisfied. '
            'If the module has no dependency, it is always installed.'),
        'state':
        fields.selection([('uninstallable', 'Not Installable'),
                          ('uninstalled', 'Not Installed'),
                          ('installed', 'Installed'),
                          ('to upgrade', 'To be upgraded'),
                          ('to remove', 'To be removed'),
                          ('to install', 'To be installed')],
                         string='Status',
                         readonly=True,
                         select=True),
        'demo':
        fields.boolean('Demo Data', readonly=True),
        'license':
        fields.selection(
            [('GPL-2', 'GPL Version 2'),
             ('GPL-2 or any later version', 'GPL-2 or later version'),
             ('GPL-3', 'GPL Version 3'),
             ('GPL-3 or any later version', 'GPL-3 or later version'),
             ('AGPL-3', 'Affero GPL-3'), ('LGPL-3', 'LGPL Version 3'),
             ('Other OSI approved licence', 'Other OSI Approved Licence'),
             ('Other proprietary', 'Other Proprietary')],
            string='License',
            readonly=True),
        'menus_by_module':
        fields.function(_get_views,
                        string='Menus',
                        type='text',
                        multi="meta",
                        store=True),
        'reports_by_module':
        fields.function(_get_views,
                        string='Reports',
                        type='text',
                        multi="meta",
                        store=True),
        'views_by_module':
        fields.function(_get_views,
                        string='Views',
                        type='text',
                        multi="meta",
                        store=True),
        'application':
        fields.boolean('Application', readonly=True),
        'icon':
        fields.char('Icon URL'),
        'icon_image':
        fields.function(_get_icon_image, string='Icon', type="binary"),
    }

    _defaults = {
        'state': 'uninstalled',
        'sequence': 100,
        'demo': False,
        'license': 'AGPL-3',
    }
    _order = 'sequence,name'

    def _name_uniq_msg(self, cr, uid, ids, context=None):
        return _('The name of the module must be unique !')

    _sql_constraints = [
        ('name_uniq', 'UNIQUE (name)', _name_uniq_msg),
    ]

    def unlink(self, cr, uid, ids, context=None):
        if not ids:
            return True
        if isinstance(ids, (int, long)):
            ids = [ids]
        mod_names = []
        for mod in self.read(cr, uid, ids, ['state', 'name'], context):
            if mod['state'] in ('installed', 'to upgrade', 'to remove',
                                'to install'):
                raise UserError(
                    _('You try to remove a module that is installed or will be installed'
                      ))
            mod_names.append(mod['name'])
        #Removing the entry from ir_model_data
        #ids_meta = self.pool.get('ir.model.data').search(cr, uid, [('name', '=', 'module_meta_information'), ('module', 'in', mod_names)])

        #if ids_meta:
        #    self.pool.get('ir.model.data').unlink(cr, uid, ids_meta, context)

        return super(module, self).unlink(cr, uid, ids, context=context)

    @staticmethod
    def _check_external_dependencies(terp):
        depends = terp.get('external_dependencies')
        if not depends:
            return
        for pydep in depends.get('python', []):
            try:
                importlib.import_module(pydep)
            except ImportError:
                raise ImportError('No module named %s' % (pydep, ))

        for binary in depends.get('bin', []):
            try:
                tools.find_in_path(binary)
            except IOError:
                raise Exception('Unable to find %r in path' % (binary, ))

    @classmethod
    def check_external_dependencies(cls, module_name, newstate='to install'):
        terp = cls.get_module_info(module_name)
        try:
            cls._check_external_dependencies(terp)
        except Exception, e:
            if newstate == 'to install':
                msg = _(
                    'Unable to install module "%s" because an external dependency is not met: %s'
                )
            elif newstate == 'to upgrade':
                msg = _(
                    'Unable to upgrade module "%s" because an external dependency is not met: %s'
                )
            else:
                msg = _(
                    'Unable to process module "%s" because an external dependency is not met: %s'
                )
            raise UserError(msg % (module_name, e.args[0]))
Exemplo n.º 3
0
class tms_maintenance_order(osv.Model):
    _inherit = ['mail.thread', 'ir.needaction_mixin']
    _name = 'tms.maintenance.order'
    _description = 'Order Maintenace'

    ########################### Columnas : Atributos #######################################################################
    _columns = {
        'name':
        fields.char('Order Maintenance'),
        'description':
        fields.char('Description'),
        'notes':
        fields.text('Notes'),
        'state':
        fields.selection([('draft', 'Draft'), ('confirmed', 'Confirmed'),
                          ('done', 'Done'), ('cancel', 'Cancelled')],
                         'Estados'),
        'cheduled_start':
        fields.datetime('Cheduled Start'),
        'cheduled_end':
        fields.datetime('Cheduled End'),
        'cheduled_start_real':
        fields.datetime('Cheduled Start Real'),
        'cheduled_end_real':
        fields.datetime('Cheduled End Real'),

        ########Many2One###########
        'unit_id':
        fields.many2one('tms.unit', 'Unit'),
        'concept_id':
        fields.many2one('product.product', 'Concept Maintenance'),
        'supervisor_id':
        fields.many2one('hr.employee', 'Supervisor'),
        'driver_report_id':
        fields.many2one('hr.employee', 'Driver Report'),
        'user_register_order_id':
        fields.many2one('hr.employee', 'User Register Report'),

        ########One2Many###########
        'activities_ids':
        fields.one2many('tms.maintenance.order.activity',
                        'maintenance_order_id', 'Activities'),
    }

    ########################### Metodos ####################################################################################

    ########## Metodos para el 'state' ##########
    def action_draft(self, cr, uid, ids, context={}):
        self.write(cr, uid, ids, {'state': 'draft'})
        return True

    def action_confirmed(self, cr, uid, ids, context=None):
        self.write(cr, uid, ids, {'state': 'confirmed'})
        return True

    def action_done(self, cr, uid, ids, context={}):
        self.write(cr, uid, ids, {'state': 'done'})
        return True

    def action_cancel(self, cr, uid, ids, context=None):
        self.write(cr, uid, ids, {'state': 'cancel'})
        return True

########################### Valores por Defecto ########################################################################

    _defaults = {
        'state': lambda *a: 'draft',
    }

    ########################### Criterio de ordenamiento ###################################################################
    _order = 'name'
Exemplo n.º 4
0
        'author': fields.char("Author", size=128, readonly=True),
        'maintainer': fields.char('Maintainer', size=128, readonly=True),
        'contributors': fields.text('Contributors', readonly=True),
        'website': fields.char("Website", size=256, readonly=True),

        # attention: Incorrect field names !!
        #   installed_version refers the latest version (the one on disk)
        #   latest_version refers the installed version (the one in database)
        #   published_version refers the version available on the repository
        'installed_version': fields.function(_get_latest_version, string='Latest Version', type='char'),
        'latest_version': fields.char('Installed Version', size=64, readonly=True),
        'published_version': fields.char('Published Version', size=64, readonly=True),

        'url': fields.char('URL', size=128, readonly=True),
        'sequence': fields.integer('Sequence'),
        'dependencies_id': fields.one2many('ir.module.module.dependency', 'module_id', 'Dependencies', readonly=True),
        'auto_install': fields.boolean('Automatic Installation',
                                       help='An auto-installable module is automatically installed by the '
                                            'system when all its dependencies are satisfied. '
                                            'If the module has no dependency, it is always installed.'),
        'state': fields.selection([
            ('uninstallable', 'Not Installable'),
            ('uninstalled', 'Not Installed'),
            ('installed', 'Installed'),
            ('to upgrade', 'To be upgraded'),
            ('to remove', 'To be removed'),
            ('to install', 'To be installed')
        ], string='Status', readonly=True, select=True),
        'demo': fields.boolean('Demo Data', readonly=True),
        'license': fields.selection([
            ('GPL-2', 'GPL Version 2'),
Exemplo n.º 5
0
                    except osv.except_osv, e:
                        # no suitable delivery method found, probably configuration error
                        _logger.error("Carrier %s: %s\n%s" % (carrier.name, e.name, e.value))
                        price = 0.0
                else:
                    price = 0.0
            res[carrier.id] = {"price": price, "available": available}
        return res

    _columns = {
        "name": fields.char("Delivery Method", required=True),
        "partner_id": fields.many2one(
            "res.partner", "Transport Company", required=True, help="The partner that is doing the delivery service."
        ),
        "product_id": fields.many2one("product.product", "Delivery Product", required=True),
        "grids_id": fields.one2many("delivery.grid", "carrier_id", "Delivery Grids"),
        "available": fields.function(
            get_price,
            string="Available",
            type="boolean",
            multi="price",
            help="Is the carrier method possible with the current order.",
        ),
        "price": fields.function(get_price, string="Price", multi="price"),
        "active": fields.boolean(
            "Active",
            help="If the active field is set to False, it will allow you to hide the delivery carrier without removing it.",
        ),
        "normal_price": fields.float(
            "Normal Price", help="Keep empty if the pricing depends on the advanced pricing per destination"
        ),
Exemplo n.º 6
0
        'ups_shipper_id': fields.many2one('ups.account.shipping', 'Shipping Account'),
=======
        'ups_shipper_id': fields.many2one('ups.account.shipping', 'Shipper'),
>>>>>>> c1979f64b3360c86d60e00c92be0271d89f97f2d
        'ups_service_id': fields.many2one('ups.shipping.service.type', 'Service Type'),
        'ups_pickup_type': fields.selection([
            ('01', 'Daily Pickup'),
            ('03', 'Customer Counter'),
            ('06', 'One Time Pickup'),
            ('07', 'On Call Air'),
            ('11', 'Suggested Retail Rates'),
            ('19', 'Letter Center'),
            ('20', 'Air Service Center'),
            ], 'Pickup Type'),
        'ups_packaging_type': fields.many2one('shipping.package.type', 'Packaging Type'),
        'shipping_rates': fields.one2many('shipping.rates.sales', 'sales_id', 'Rate Quotes'),
        'status_message': fields.char('Status', size=128, readonly=True),
        # From partner address validation
        'address_validation_method': fields.selection(_method_get, 'Address Validation Method', size=32),
        
    }

    def _get_sale_account(self, cr, uid, context=None):
        if context is None:
            context = {}
        logsitic_obj = self.pool.get('logistic.company')
        user_rec = self.pool.get('res.users').browse(cr , uid, uid, context)
        logis_company = logsitic_obj.search(cr, uid, [])
        if not logis_company:
            return False
        return logsitic_obj.browse(cr, uid, logis_company[0], context).ship_account_id.id
FISCAL_RULE_COLUMNS = {
    "partner_fiscal_type_id": fields.many2one("l10n_br_account.partner.fiscal.type", "Tipo Fiscal do Parceiro"),
    "fiscal_category_id": fields.many2one("l10n_br_account.fiscal.category", "Categoria"),
    "fiscal_type": fields.selection(COMPANY_FISCAL_TYPE, u"Regime Tributário", required=True),
    "revenue_start": fields.float(
        "Faturamento Inicial", digits_compute=dp.get_precision("Account"), help="Faixa inicial de faturamento bruto"
    ),
    "revenue_end": fields.float(
        "Faturamento Final", digits_compute=dp.get_precision("Account"), help="Faixa inicial de faturamento bruto"
    ),
}

OTHERS_FISCAL_RULE_COLUMNS_TEMPLATE = {
    "parent_id": fields.many2one("account.fiscal.position.rule.template", "Regra Pai"),
    "child_ids": fields.one2many("account.fiscal.position.rule.template", "parent_id", "Regras Filhas"),
}

OTHERS_FISCAL_RULE_COLUMNS = {
    "parent_id": fields.many2one("account.fiscal.position.rule", "Regra Pai"),
    "child_ids": fields.one2many("account.fiscal.position.rule", "parent_id", "Regras Filhas"),
}

FISCAL_RULE_DEFAULTS = {"fiscal_type": COMPANY_FISCAL_TYPE_DEFAULT, "revenue_start": 0.00, "revenue_end": 0.00}


class AccountFiscalPositionRuleTemplate(orm.Model):
    _inherit = "account.fiscal.position.rule.template"
    _columns = dict(FISCAL_RULE_COLUMNS.items() + OTHERS_FISCAL_RULE_COLUMNS_TEMPLATE.items())
    _defaults = FISCAL_RULE_DEFAULTS
Exemplo n.º 8
0
	_columns = {
		'name' : fields.char('Name', required=True),
		'partner_id' : fields.many2one('res.partner','Principle',domain=[('supplier','=',True)],required=True),
		'product_id' : fields.many2one('product.product','Bonus Product'),
		'qty_2' : fields.float('Bonus Qty2', digits_compute=dp.get_precision('Product Unit of Measure')),
		'qty' : fields.function(_qty_all_1,type="float",string='Bonus Qty',digits_compute=dp.get_precision('Product Unit of Measure')),
		'uom_id' : fields.many2one('product.uom','UoM',required=True),
		'uom_id2' : fields.many2one('product.uom','UoM',required=True),
		'value' : fields.float('Price Value',domain=[('is_percent','=',False)]),
		'per_product' : fields.boolean('Per Product'),
		'persentase' : fields.float('Percent Value', digits_compute= dp.get_precision('Discount'),domain=[('is_percent','=',True)]),
		'multi' : fields.boolean('Multiples'),
		'is_active' : fields.boolean('Active?'),
		'date_from' : fields.date('Start Date', required=True),
		'date_to' : fields.date('End Date', required=True),
		'condition_ids' : fields.one2many('master.condition','discount_id','Value Condition'),
		'condition2_ids' : fields.one2many('master.condition2','discount_id','Product Condition'),
		'condition3_ids' : fields.one2many('master.condition3','discount_id','Product Condition 2'),
		'condition4_ids' : fields.one2many('master.condition4','discount_id','Product Condition 3'),
		'condition5_ids' : fields.one2many('master.condition5','discount_id','Product Condition 4'),
		'group_price_ids' : fields.many2many('res.partner.category', id1='discount_id', id2='category_id', string='Group Price Category'),
		'is_percent' : fields.boolean('Is Percent'),
		'is_flat' : fields.boolean('Flat'),
		'type' :fields.selection([('regular','Regular Discount'),('promo','Promo Discount'),('extra','Extra Discount'),('cash','Cash Discount'),('mix','Mix Discount')],string='Type Discount',required=True),
		'min_qty_product' : fields.float('Min. Product Item',digits_compute=dp.get_precision('Product Unit of Measure')),
		'multi2' : fields.boolean('Value Condition'),
		'multi3' : fields.boolean('Multiples for New Product'),
		# 'multi_sel' : fields.selection([('general','General Multiples'),('specific','Specific Multiples for New Product')],string="Multiples"),
		'product_id2' : fields.many2one('product.product','Bonus New Product'),
		'qty2_2' : fields.float('Bonus Qty', digits_compute=dp.get_precision('Product Unit of Measure')),
		'qty2' : fields.function(_qty_all_2,type="float",string='Bonus Qty',digits_compute=dp.get_precision('Product Unit of Measure')),
Exemplo n.º 9
0
class MergePartnerAutomatic(osv.TransientModel):
    """
        The idea behind this wizard is to create a list of potential partners to
        merge. We use two objects, the first one is the wizard for the end-user.
        And the second will contain the partner list to merge.
    """
    _name = 'base.partner.merge.automatic.wizard'

    _columns = {
        # Group by
        'group_by_email':
        fields.boolean('Email'),
        'group_by_name':
        fields.boolean('Name'),
        'group_by_is_company':
        fields.boolean('Is Company'),
        'group_by_vat':
        fields.boolean('VAT'),
        'group_by_parent_id':
        fields.boolean('Parent Company'),
        'state':
        fields.selection([('option', 'Option'), ('selection', 'Selection'),
                          ('finished', 'Finished')],
                         'State',
                         readonly=True,
                         required=True),
        'number_group':
        fields.integer("Group of Contacts", readonly=True),
        'current_line_id':
        fields.many2one('base.partner.merge.line', 'Current Line'),
        'line_ids':
        fields.one2many('base.partner.merge.line', 'wizard_id', 'Lines'),
        'partner_ids':
        fields.many2many('res.partner', string='Contacts'),
        'dst_partner_id':
        fields.many2one('res.partner', string='Destination Contact'),
        'exclude_contact':
        fields.boolean('A user associated to the contact'),
        'exclude_journal_item':
        fields.boolean('Journal Items associated to the contact'),
        'maximum_group':
        fields.integer("Maximum of Group of Contacts"),
    }

    def default_get(self, cr, uid, fields, context=None):
        if context is None:
            context = {}
        res = super(MergePartnerAutomatic,
                    self).default_get(cr, uid, fields, context)
        if context.get('active_model') == 'res.partner' and context.get(
                'active_ids'):
            partner_ids = context['active_ids']
            res['state'] = 'selection'
            res['partner_ids'] = partner_ids
            res['dst_partner_id'] = self._get_ordered_partner(
                cr, uid, partner_ids, context=context)[-1].id
        return res

    _defaults = {'state': 'option'}

    def get_fk_on(self, cr, table):
        q = """  SELECT cl1.relname as table,
                        att1.attname as column
                   FROM pg_constraint as con, pg_class as cl1, pg_class as cl2,
                        pg_attribute as att1, pg_attribute as att2
                  WHERE con.conrelid = cl1.oid
                    AND con.confrelid = cl2.oid
                    AND array_lower(con.conkey, 1) = 1
                    AND con.conkey[1] = att1.attnum
                    AND att1.attrelid = cl1.oid
                    AND cl2.relname = %s
                    AND att2.attname = 'id'
                    AND array_lower(con.confkey, 1) = 1
                    AND con.confkey[1] = att2.attnum
                    AND att2.attrelid = cl2.oid
                    AND con.contype = 'f'
        """
        return cr.execute(q, (table, ))

    def _update_foreign_keys(self,
                             cr,
                             uid,
                             src_partners,
                             dst_partner,
                             context=None):
        _logger.debug(
            '_update_foreign_keys for dst_partner: %s for src_partners: %r',
            dst_partner.id, list(map(operator.attrgetter('id'), src_partners)))

        # find the many2one relation to a partner
        proxy = self.pool.get('res.partner')
        self.get_fk_on(cr, 'res_partner')

        # ignore two tables

        for table, column in cr.fetchall():
            if 'base_partner_merge_' in table:
                continue
            partner_ids = tuple(map(int, src_partners))

            query = "SELECT column_name FROM information_schema.columns WHERE table_name LIKE '%s'" % (
                table)
            cr.execute(query, ())
            columns = []
            for data in cr.fetchall():
                if data[0] != column:
                    columns.append(data[0])

            query_dic = {
                'table': table,
                'column': column,
                'value': columns[0],
            }
            if len(columns) <= 1:
                # unique key treated
                query = """
                    UPDATE "%(table)s" as ___tu
                    SET %(column)s = %%s
                    WHERE
                        %(column)s = %%s AND
                        NOT EXISTS (
                            SELECT 1
                            FROM "%(table)s" as ___tw
                            WHERE
                                %(column)s = %%s AND
                                ___tu.%(value)s = ___tw.%(value)s
                        )""" % query_dic
                for partner_id in partner_ids:
                    cr.execute(query,
                               (dst_partner.id, partner_id, dst_partner.id))
            else:
                try:
                    with mute_logger('openerp.sql_db'), cr.savepoint():
                        query = 'UPDATE "%(table)s" SET %(column)s = %%s WHERE %(column)s IN %%s' % query_dic
                        cr.execute(query, (
                            dst_partner.id,
                            partner_ids,
                        ))

                        if column == proxy._parent_name and table == 'res_partner':
                            query = """
                                WITH RECURSIVE cycle(id, parent_id) AS (
                                        SELECT id, parent_id FROM res_partner
                                    UNION
                                        SELECT  cycle.id, res_partner.parent_id
                                        FROM    res_partner, cycle
                                        WHERE   res_partner.id = cycle.parent_id AND
                                                cycle.id != cycle.parent_id
                                )
                                SELECT id FROM cycle WHERE id = parent_id AND id = %s
                            """
                            cr.execute(query, (dst_partner.id, ))
                except psycopg2.Error:
                    # updating fails, most likely due to a violated unique constraint
                    # keeping record with nonexistent partner_id is useless, better delete it
                    query = 'DELETE FROM %(table)s WHERE %(column)s = %%s' % query_dic
                    cr.execute(query, (partner_id, ))

    def _update_reference_fields(self,
                                 cr,
                                 uid,
                                 src_partners,
                                 dst_partner,
                                 context=None):
        _logger.debug(
            '_update_reference_fields for dst_partner: %s for src_partners: %r',
            dst_partner.id, list(map(operator.attrgetter('id'), src_partners)))

        def update_records(model,
                           src,
                           field_model='model',
                           field_id='res_id',
                           context=None):
            proxy = self.pool.get(model)
            if proxy is None:
                return
            domain = [(field_model, '=', 'res.partner'),
                      (field_id, '=', src.id)]
            ids = proxy.search(cr,
                               openerp.SUPERUSER_ID,
                               domain,
                               context=context)
            try:
                with mute_logger('openerp.sql_db'), cr.savepoint():
                    return proxy.write(cr,
                                       openerp.SUPERUSER_ID,
                                       ids, {field_id: dst_partner.id},
                                       context=context)
            except psycopg2.Error:
                # updating fails, most likely due to a violated unique constraint
                # keeping record with nonexistent partner_id is useless, better delete it
                return proxy.unlink(cr,
                                    openerp.SUPERUSER_ID,
                                    ids,
                                    context=context)

        update_records = functools.partial(update_records, context=context)

        for partner in src_partners:
            update_records('calendar',
                           src=partner,
                           field_model='model_id.model')
            update_records('ir.attachment',
                           src=partner,
                           field_model='res_model')
            update_records('mail.followers',
                           src=partner,
                           field_model='res_model')
            update_records('mail.message', src=partner)
            update_records('marketing.campaign.workitem',
                           src=partner,
                           field_model='object_id.model')
            update_records('ir.model.data', src=partner)

        proxy = self.pool['ir.model.fields']
        domain = [('ttype', '=', 'reference')]
        record_ids = proxy.search(cr,
                                  openerp.SUPERUSER_ID,
                                  domain,
                                  context=context)

        for record in proxy.browse(cr,
                                   openerp.SUPERUSER_ID,
                                   record_ids,
                                   context=context):
            try:
                proxy_model = self.pool[record.model]
                field_type = proxy_model._columns[record.name].__class__._type
            except KeyError:
                # unknown model or field => skip
                continue

            if field_type == 'function':
                continue

            for partner in src_partners:
                domain = [(record.name, '=', 'res.partner,%d' % partner.id)]
                model_ids = proxy_model.search(cr,
                                               openerp.SUPERUSER_ID,
                                               domain,
                                               context=context)
                values = {
                    record.name: 'res.partner,%d' % dst_partner.id,
                }
                proxy_model.write(cr,
                                  openerp.SUPERUSER_ID,
                                  model_ids,
                                  values,
                                  context=context)

    def _update_values(self, cr, uid, src_partners, dst_partner, context=None):
        _logger.debug(
            '_update_values for dst_partner: %s for src_partners: %r',
            dst_partner.id, list(map(operator.attrgetter('id'), src_partners)))

        columns = dst_partner._columns

        def write_serializer(column, item):
            if isinstance(item, browse_record):
                return item.id
            else:
                return item

        values = dict()
        for column, field in columns.iteritems():
            if field._type not in ('many2many', 'one2many') and not isinstance(
                    field, fields.function):
                for item in itertools.chain(src_partners, [dst_partner]):
                    if item[column]:
                        values[column] = write_serializer(column, item[column])

        values.pop('id', None)
        parent_id = values.pop('parent_id', None)
        dst_partner.write(values)
        if parent_id and parent_id != dst_partner.id:
            try:
                dst_partner.write({'parent_id': parent_id})
            except (osv.except_osv, orm.except_orm):
                _logger.info(
                    'Skip recursive partner hierarchies for parent_id %s of partner: %s',
                    parent_id, dst_partner.id)

    @mute_logger('openerp.osv.expression', 'openerp.models')
    def _merge(self, cr, uid, partner_ids, dst_partner=None, context=None):
        proxy = self.pool.get('res.partner')

        partner_ids = proxy.exists(cr, uid, list(partner_ids), context=context)
        if len(partner_ids) < 2:
            return

        if len(partner_ids) > 3:
            raise osv.except_osv(
                _('Error'),
                _("For safety reasons, you cannot merge more than 3 contacts together. You can re-open the wizard several times if needed."
                  ))

        if openerp.SUPERUSER_ID != uid and len(
                set(partner.email for partner in proxy.browse(
                    cr, uid, partner_ids, context=context))) > 1:
            raise osv.except_osv(
                _('Error'),
                _("All contacts must have the same email. Only the Administrator can merge contacts with different emails."
                  ))

        if dst_partner and dst_partner.id in partner_ids:
            src_partners = proxy.browse(
                cr,
                uid, [id for id in partner_ids if id != dst_partner.id],
                context=context)
        else:
            ordered_partners = self._get_ordered_partner(
                cr, uid, partner_ids, context)
            dst_partner = ordered_partners[-1]
            src_partners = ordered_partners[:-1]
        _logger.info("dst_partner: %s", dst_partner.id)

        if openerp.SUPERUSER_ID != uid and self._model_is_installed(cr, uid, 'account.move.line', context=context) and \
                self.pool.get('account.move.line').search(cr, openerp.SUPERUSER_ID, [('partner_id', 'in', [partner.id for partner in src_partners])], context=context):
            raise osv.except_osv(
                _('Error'),
                _("Only the destination contact may be linked to existing Journal Items. Please ask the Administrator if you need to merge several contacts linked to existing Journal Items."
                  ))

        call_it = lambda function: function(
            cr, uid, src_partners, dst_partner, context=context)

        call_it(self._update_foreign_keys)
        call_it(self._update_reference_fields)
        call_it(self._update_values)

        _logger.info('(uid = %s) merged the partners %r with %s', uid,
                     list(map(operator.attrgetter('id'), src_partners)),
                     dst_partner.id)
        dst_partner.message_post(body='%s %s' %
                                 (_("Merged with the following partners:"),
                                  ", ".join('%s<%s>(ID %s)' %
                                            (p.name, p.email or 'n/a', p.id)
                                            for p in src_partners)))

        for partner in src_partners:
            partner.unlink()

    def clean_emails(self, cr, uid, context=None):
        """
        Clean the email address of the partner, if there is an email field with
        a mimum of two addresses, the system will create a new partner, with the
        information of the previous one and will copy the new cleaned email into
        the email field.
        """
        context = dict(context or {})

        proxy_model = self.pool['ir.model.fields']
        field_ids = proxy_model.search(cr,
                                       uid, [('model', '=', 'res.partner'),
                                             ('ttype', 'like', '%2many')],
                                       context=context)
        fields = proxy_model.read(cr, uid, field_ids, context=context)
        reset_fields = dict((field['name'], []) for field in fields)

        proxy_partner = self.pool['res.partner']
        context['active_test'] = False
        ids = proxy_partner.search(cr, uid, [], context=context)

        fields = ['name', 'var' 'partner_id' 'is_company', 'email']
        partners = proxy_partner.read(cr, uid, ids, fields, context=context)

        partners.sort(key=operator.itemgetter('id'))
        partners_len = len(partners)

        _logger.info('partner_len: %r', partners_len)

        for idx, partner in enumerate(partners):
            if not partner['email']:
                continue

            percent = (idx / float(partners_len)) * 100.0
            _logger.info('idx: %r', idx)
            _logger.info('percent: %r', percent)
            try:
                emails = sanitize_email(partner['email'])
                head, tail = emails[:1], emails[1:]
                email = head[0] if head else False

                proxy_partner.write(cr,
                                    uid, [partner['id']], {'email': email},
                                    context=context)

                for email in tail:
                    values = dict(reset_fields, email=email)
                    proxy_partner.copy(cr,
                                       uid,
                                       partner['id'],
                                       values,
                                       context=context)

            except Exception:
                _logger.exception("There is a problem with this partner: %r",
                                  partner)
                raise
        return True

    def close_cb(self, cr, uid, ids, context=None):
        return {'type': 'ir.actions.act_window_close'}

    def _generate_query(self, fields, maximum_group=100):
        sql_fields = []
        for field in fields:
            if field in ['email', 'name']:
                sql_fields.append('lower(%s)' % field)
            elif field in ['vat']:
                sql_fields.append("replace(%s, ' ', '')" % field)
            else:
                sql_fields.append(field)

        group_fields = ', '.join(sql_fields)

        filters = []
        for field in fields:
            if field in ['email', 'name', 'vat']:
                filters.append((field, 'IS NOT', 'NULL'))

        criteria = ' AND '.join('%s %s %s' % (field, operator, value)
                                for field, operator, value in filters)

        text = [
            "SELECT min(id), array_agg(id)",
            "FROM res_partner",
        ]

        if criteria:
            text.append('WHERE %s' % criteria)

        text.extend([
            "GROUP BY %s" % group_fields,
            "HAVING COUNT(*) >= 2",
            "ORDER BY min(id)",
        ])

        if maximum_group:
            text.extend([
                "LIMIT %s" % maximum_group,
            ])

        return ' '.join(text)

    def _compute_selected_groupby(self, this):
        group_by_str = 'group_by_'
        group_by_len = len(group_by_str)

        fields = [
            key[group_by_len:] for key in self._columns.keys()
            if key.startswith(group_by_str)
        ]

        groups = [
            field for field in fields
            if getattr(this, '%s%s' % (group_by_str, field), False)
        ]

        if not groups:
            raise osv.except_osv(
                _('Error'),
                _("You have to specify a filter for your selection"))

        return groups

    def next_cb(self, cr, uid, ids, context=None):
        """
        Don't compute any thing
        """
        context = dict(context or {}, active_test=False)
        this = self.browse(cr, uid, ids[0], context=context)
        if this.current_line_id:
            this.current_line_id.unlink()
        return self._next_screen(cr, uid, this, context)

    def _get_ordered_partner(self, cr, uid, partner_ids, context=None):
        partners = self.pool.get('res.partner').browse(cr,
                                                       uid,
                                                       list(partner_ids),
                                                       context=context)
        ordered_partners = sorted(sorted(
            partners, key=operator.attrgetter('create_date'), reverse=True),
                                  key=operator.attrgetter('active'),
                                  reverse=True)
        return ordered_partners

    def _next_screen(self, cr, uid, this, context=None):
        this.refresh()
        values = {}
        if this.line_ids:
            # in this case, we try to find the next record.
            current_line = this.line_ids[0]
            current_partner_ids = literal_eval(current_line.aggr_ids)
            values.update({
                'current_line_id':
                current_line.id,
                'partner_ids': [(6, 0, current_partner_ids)],
                'dst_partner_id':
                self._get_ordered_partner(cr, uid, current_partner_ids,
                                          context)[-1].id,
                'state':
                'selection',
            })
        else:
            values.update({
                'current_line_id': False,
                'partner_ids': [],
                'state': 'finished',
            })

        this.write(values)

        return {
            'type': 'ir.actions.act_window',
            'res_model': this._name,
            'res_id': this.id,
            'view_mode': 'form',
            'target': 'new',
        }

    def _model_is_installed(self, cr, uid, model, context=None):
        proxy = self.pool.get('ir.model')
        domain = [('model', '=', model)]
        return proxy.search_count(cr, uid, domain, context=context) > 0

    def _partner_use_in(self, cr, uid, aggr_ids, models, context=None):
        """
        Check if there is no occurence of this group of partner in the selected
        model
        """
        for model, field in models.iteritems():
            proxy = self.pool.get(model)
            domain = [(field, 'in', aggr_ids)]
            if proxy.search_count(cr, uid, domain, context=context):
                return True
        return False

    def compute_models(self, cr, uid, ids, context=None):
        """
        Compute the different models needed by the system if you want to exclude
        some partners.
        """
        assert is_integer_list(ids)

        this = self.browse(cr, uid, ids[0], context=context)

        models = {}
        if this.exclude_contact:
            models['res.users'] = 'partner_id'

        if self._model_is_installed(
                cr, uid, 'account.move.line',
                context=context) and this.exclude_journal_item:
            models['account.move.line'] = 'partner_id'

        return models

    def _process_query(self, cr, uid, ids, query, context=None):
        """
        Execute the select request and write the result in this wizard
        """
        proxy = self.pool.get('base.partner.merge.line')
        this = self.browse(cr, uid, ids[0], context=context)
        models = self.compute_models(cr, uid, ids, context=context)
        cr.execute(query)

        counter = 0
        for min_id, aggr_ids in cr.fetchall():
            if models and self._partner_use_in(
                    cr, uid, aggr_ids, models, context=context):
                continue
            values = {
                'wizard_id': this.id,
                'min_id': min_id,
                'aggr_ids': aggr_ids,
            }

            proxy.create(cr, uid, values, context=context)
            counter += 1

        values = {
            'state': 'selection',
            'number_group': counter,
        }

        this.write(values)

        _logger.info("counter: %s", counter)

    def start_process_cb(self, cr, uid, ids, context=None):
        """
        Start the process.
        * Compute the selected groups (with duplication)
        * If the user has selected the 'exclude_XXX' fields, avoid the partners.
        """
        assert is_integer_list(ids)

        context = dict(context or {}, active_test=False)
        this = self.browse(cr, uid, ids[0], context=context)
        groups = self._compute_selected_groupby(this)
        query = self._generate_query(groups, this.maximum_group)
        self._process_query(cr, uid, ids, query, context=context)

        return self._next_screen(cr, uid, this, context)

    def automatic_process_cb(self, cr, uid, ids, context=None):
        assert is_integer_list(ids)
        this = self.browse(cr, uid, ids[0], context=context)
        this.start_process_cb()
        this.refresh()

        for line in this.line_ids:
            partner_ids = literal_eval(line.aggr_ids)
            self._merge(cr, uid, partner_ids, context=context)
            line.unlink()
            cr.commit()

        this.write({'state': 'finished'})
        return {
            'type': 'ir.actions.act_window',
            'res_model': this._name,
            'res_id': this.id,
            'view_mode': 'form',
            'target': 'new',
        }

    def parent_migration_process_cb(self, cr, uid, ids, context=None):
        assert is_integer_list(ids)

        context = dict(context or {}, active_test=False)
        this = self.browse(cr, uid, ids[0], context=context)

        query = """
            SELECT
                min(p1.id),
                array_agg(DISTINCT p1.id)
            FROM
                res_partner as p1
            INNER join
                res_partner as p2
            ON
                p1.email = p2.email AND
                p1.name = p2.name AND
                (p1.parent_id = p2.id OR p1.id = p2.parent_id)
            WHERE
                p2.id IS NOT NULL
            GROUP BY
                p1.email,
                p1.name,
                CASE WHEN p1.parent_id = p2.id THEN p2.id
                    ELSE p1.id
                END
            HAVING COUNT(*) >= 2
            ORDER BY
                min(p1.id)
        """

        self._process_query(cr, uid, ids, query, context=context)

        for line in this.line_ids:
            partner_ids = literal_eval(line.aggr_ids)
            self._merge(cr, uid, partner_ids, context=context)
            line.unlink()
            cr.commit()

        this.write({'state': 'finished'})

        cr.execute("""
            UPDATE
                res_partner
            SET
                is_company = NULL,
                parent_id = NULL
            WHERE
                parent_id = id
        """)

        return {
            'type': 'ir.actions.act_window',
            'res_model': this._name,
            'res_id': this.id,
            'view_mode': 'form',
            'target': 'new',
        }

    def update_all_process_cb(self, cr, uid, ids, context=None):
        assert is_integer_list(ids)

        # WITH RECURSIVE cycle(id, parent_id) AS (
        #     SELECT id, parent_id FROM res_partner
        #   UNION
        #     SELECT  cycle.id, res_partner.parent_id
        #     FROM    res_partner, cycle
        #     WHERE   res_partner.id = cycle.parent_id AND
        #             cycle.id != cycle.parent_id
        # )
        # UPDATE  res_partner
        # SET     parent_id = NULL
        # WHERE   id in (SELECT id FROM cycle WHERE id = parent_id);

        this = self.browse(cr, uid, ids[0], context=context)

        self.parent_migration_process_cb(cr, uid, ids, context=None)

        list_merge = [
            {
                'group_by_vat': True,
                'group_by_email': True,
                'group_by_name': True
            },
            # {'group_by_name': True, 'group_by_is_company': True, 'group_by_parent_id': True},
            # {'group_by_email': True, 'group_by_is_company': True, 'group_by_parent_id': True},
            # {'group_by_name': True, 'group_by_vat': True, 'group_by_is_company': True, 'exclude_journal_item': True},
            # {'group_by_email': True, 'group_by_vat': True, 'group_by_is_company': True, 'exclude_journal_item': True},
            # {'group_by_email': True, 'group_by_is_company': True, 'exclude_contact': True, 'exclude_journal_item': True},
            # {'group_by_name': True, 'group_by_is_company': True, 'exclude_contact': True, 'exclude_journal_item': True}
        ]

        for merge_value in list_merge:
            id = self.create(cr, uid, merge_value, context=context)
            self.automatic_process_cb(cr, uid, [id], context=context)

        cr.execute("""
            UPDATE
                res_partner
            SET
                is_company = NULL
            WHERE
                parent_id IS NOT NULL AND
                is_company IS NOT NULL
        """)

        # cr.execute("""
        #     UPDATE
        #         res_partner as p1
        #     SET
        #         is_company = NULL,
        #         parent_id = (
        #             SELECT  p2.id
        #             FROM    res_partner as p2
        #             WHERE   p2.email = p1.email AND
        #                     p2.parent_id != p2.id
        #             LIMIT 1
        #         )
        #     WHERE
        #         p1.parent_id = p1.id
        # """)

        return self._next_screen(cr, uid, this, context)

    def merge_cb(self, cr, uid, ids, context=None):
        assert is_integer_list(ids)

        context = dict(context or {}, active_test=False)
        this = self.browse(cr, uid, ids[0], context=context)

        partner_ids = set(map(int, this.partner_ids))
        if not partner_ids:
            this.write({'state': 'finished'})
            return {
                'type': 'ir.actions.act_window',
                'res_model': this._name,
                'res_id': this.id,
                'view_mode': 'form',
                'target': 'new',
            }

        self._merge(cr, uid, partner_ids, this.dst_partner_id, context=context)

        if this.current_line_id:
            this.current_line_id.unlink()

        return self._next_screen(cr, uid, this, context)

    def auto_set_parent_id(self, cr, uid, ids, context=None):
        assert is_integer_list(ids)

        # select partner who have one least invoice
        partner_treated = ['@gmail.com']
        cr.execute("""  SELECT p.id, p.email
                        FROM res_partner as p 
                        LEFT JOIN account_invoice as a 
                        ON p.id = a.partner_id AND a.state in ('open','paid')
                        WHERE p.grade_id is NOT NULL
                        GROUP BY p.id
                        ORDER BY COUNT(a.id) DESC
                """)
        re_email = re.compile(r".*@")
        for id, email in cr.fetchall():
            # check email domain
            email = re_email.sub("@", email or "")
            if not email or email in partner_treated:
                continue
            partner_treated.append(email)

            # don't update the partners if they are more of one who have invoice
            cr.execute("""  SELECT *
                            FROM res_partner as p
                            WHERE p.id != %s AND p.email LIKE '%%%s' AND
                                EXISTS (SELECT * FROM account_invoice as a WHERE p.id = a.partner_id AND a.state in ('open','paid'))
                    """ % (id, email))

            if len(cr.fetchall()) > 1:
                _logger.info("%s MORE OF ONE COMPANY", email)
                continue

            # to display changed values
            cr.execute("""  SELECT id,email
                            FROM res_partner
                            WHERE parent_id != %s AND id != %s AND email LIKE '%%%s'
                    """ % (id, id, email))
            _logger.info("%r", cr.fetchall())

            # upgrade
            cr.execute("""  UPDATE res_partner
                            SET parent_id = %s
                            WHERE id != %s AND email LIKE '%%%s'
                    """ % (id, id, email))
        return False
class hr_rpt_attend_emp_day(osv.osv_memory):
    _name = "hr.rpt.attend.emp.day"
    _inherit = "rpt.base"
    _description = "HR Attendance Employee Day Report"
    _columns = {
        #report data lines
        'rpt_lines':
        fields.one2many('hr.rpt.attend.emp.day.line',
                        'rpt_id',
                        string='Report Line'),
        'date_from':
        fields.datetime("Start Date", required=True),
        'date_to':
        fields.datetime("End Date", required=True),
        'emp_ids':
        fields.many2many('hr.employee', string='Employees'),
    }

    _defaults = {
        'type': 'attend_emp_day',
        #        'emp_ids':[342,171]
    }

    def default_get(self, cr, uid, fields, context=None):
        vals = super(hr_rpt_attend_emp_day, self).default_get(cr,
                                                              uid,
                                                              fields,
                                                              context=context)
        if 'date_from' in fields:
            #For the datetime value in defaults, need convert the local time to UTC, the web framework will convert them back to local time on GUI
            date_from = datetime.strptime(time.strftime('%Y-%m-01 00:00:00'),
                                          '%Y-%m-%d %H:%M:%S')
            date_from_utc = utils.utc_timestamp(cr, uid, date_from, context)
            vals.update({
                'date_from':
                date_from_utc.strftime(DEFAULT_SERVER_DATETIME_FORMAT)
            })

        if 'date_to' in fields:
            date_to = datetime.strptime(time.strftime('%Y-%m-%d 23:59:59'),
                                        '%Y-%m-%d %H:%M:%S')
            date_to_utc = utils.utc_timestamp(cr, uid, date_to, context)
            vals.update({
                'date_to':
                date_to_utc.strftime(DEFAULT_SERVER_DATETIME_FORMAT)
            })

        return vals

    def _check_dates(self, cr, uid, ids, context=None):
        for wiz in self.browse(cr, uid, ids, context=context):
            if wiz.date_from and wiz.date_to and wiz.date_from > wiz.date_to:
                return False
        return True

    _constraints = [
        (_check_dates, 'The date end must be after the date start.',
         ['date_from', 'date_to']),
    ]

    def get_report_name(self, cr, uid, id, rpt_name, context=None):
        return "Attendance Employee Day Report"

    def name_get(self, cr, uid, ids, context=None):
        if not ids:
            return []
        res = []
        for id in ids:
            res.append((id, '%s' % (id, )))
        return res

    def _convert_save_dates(self, cr, uid, vals, context):
        #convert to the date like '2013-01-01' to UTC datetime to store
        if 'date_from' in vals and len(vals['date_from']) == 10:
            date_from = vals['date_from']
            date_from = utils.utc_timestamp(
                cr,
                uid,
                datetime.strptime(date_from + ' 00:00:00',
                                  DEFAULT_SERVER_DATETIME_FORMAT),
                context=context)
            date_from = date_from.strftime(DEFAULT_SERVER_DATETIME_FORMAT)
            vals['date_from'] = date_from
        if 'date_to' in vals and len(vals['date_to']) == 10:
            date_to = vals['date_to']
            date_to = utils.utc_timestamp(cr,
                                          uid,
                                          datetime.strptime(
                                              date_to + ' 23:59:59',
                                              DEFAULT_SERVER_DATETIME_FORMAT),
                                          context=context)
            date_to = date_to.strftime(DEFAULT_SERVER_DATETIME_FORMAT)
            vals['date_to'] = date_to

    def create(self, cr, uid, vals, context=None):
        self._convert_save_dates(cr, uid, vals, context)
        id_new = super(hr_rpt_attend_emp_day, self).create(cr,
                                                           uid,
                                                           vals,
                                                           context=context)
        return id_new

    def write(self, cr, uid, ids, vals, context=None):
        self._convert_save_dates(cr, uid, vals, context)
        resu = super(hr_rpt_attend_emp_day, self).write(cr,
                                                        uid,
                                                        ids,
                                                        vals,
                                                        context=context)
        return resu

    def _attend_hours(self, hours_valid, period):
        '''
        if hours_valid > period.hours_work_normal:
            hours_normal = period.hours_work_normal
        else:
            hours_normal = hours_valid
        hours_ot = hours_valid - hours_normal
        if hours_ot > period.hours_work_ot:
            hours_ot = period.hours_work_ot
        #the second time group                        
        if hours_valid > period.hours_work_normal2:
            hours_normal2 = period.hours_work_normal2
        else:
            hours_normal2 = hours_valid
        hours_ot2 = hours_valid - hours_normal2
        if hours_ot2 > period.hours_work_ot2:
            hours_ot2 = period.hours_work_ot2
        '''
        if hours_valid > period.hours_work_normal:
            hours_normal = period.hours_work_normal
        else:
            hours_normal = hours_valid
        hours_ot = hours_valid - hours_normal
        if hours_ot > period.hours_work_ot:
            hours_ot = period.hours_work_ot
        #the second time group
        if hours_valid > period.hours_work_normal2:
            hours_normal2 = period.hours_work_normal2
        else:
            hours_normal2 = hours_valid
        hours_ot2 = hours_valid - hours_normal2
        if hours_ot2 > period.hours_work_ot2:
            hours_ot2 = period.hours_work_ot2
        return hours_normal, hours_ot, hours_normal2, hours_ot2

    def run_attend_emp_day(self, cr, uid, ids, context=None):
        '''
        1.Query all data with both in/out by date range, store the result in attends_normal
        2.Loop on by days and employees
        '''
        emp_obj = self.pool.get('hr.employee')
        attend_obj = self.pool.get('hr.attendance')

        if context is None: context = {}
        rpt = self.browse(cr, uid, ids, context=context)[0]
        date_from = datetime.strptime(rpt.date_from,
                                      DEFAULT_SERVER_DATETIME_FORMAT)
        date_to = datetime.strptime(rpt.date_to,
                                    DEFAULT_SERVER_DATETIME_FORMAT)
        #report data line
        rpt_lns = []
        #context for the query
        c = context.copy()
        #get the employees
        emp_ids = [emp.id for emp in rpt.emp_ids]
        if not emp_ids:
            emp_ids = emp_obj.search(cr, uid, [], context=context)
        '''
        1.Query all data with both in/out by date range, store the result in attends_normal
        '''
        sql = '''
                select emp.id as emp_id, 
                period.id as period_id, 
                sign_in.day,
                sign_in.action as in_action, sign_in.name as in_time, sign_out.action out_action, sign_out.name out_time
                from hr_employee emp
                left join 
                    (select name,employee_id,cale_period_id,action,day from hr_attendance where name between %s and %s and action in('sign_in','sign_in_late')) as sign_in
                    on emp.id = sign_in.employee_id
                left join 
                    (select name,employee_id,cale_period_id,action,day from hr_attendance where name between %s and %s and action in('sign_out','sign_out_early')) as sign_out
                    on emp.id = sign_out.employee_id and sign_in.day = sign_out.day and sign_in.cale_period_id = sign_out.cale_period_id
                join resource_calendar_attendance period on sign_in.cale_period_id = period.id and sign_out.cale_period_id = period.id
                where emp.id = ANY(%s)
                '''
        cr.execute(sql, (date_from, date_to, date_from, date_to, (emp_ids, )))
        attends = cr.dictfetchall()
        #use the emp_id-day-period_id as the key to store the normal attendance
        #        attends_normal = dict(('%s-%s-%s'%(attend['emp_id'], attend['day'], attend['period_id']), attend) for attend in attends)
        attends_normal = {}
        for attend in attends:
            key = '%s-%s-%s' % (attend['emp_id'], attend['day'],
                                attend['period_id'])
            in_time = fields.datetime.context_timestamp(
                cr,
                uid,
                datetime.strptime(attend['in_time'],
                                  DEFAULT_SERVER_DATETIME_FORMAT),
                context=context)
            out_time = fields.datetime.context_timestamp(
                cr,
                uid,
                datetime.strptime(attend['out_time'],
                                  DEFAULT_SERVER_DATETIME_FORMAT),
                context=context)
            attend['in_time'] = in_time
            attend['out_time'] = out_time
            attends_normal[key] = attend
        '''
        2.Loop on by days and employees
        '''
        date_from_local = fields.datetime.context_timestamp(
            cr, uid, date_from, context)
        date_to_local = fields.datetime.context_timestamp(
            cr, uid, date_to, context)
        days = rrule.rrule(rrule.DAILY,
                           dtstart=date_from_local,
                           until=date_to_local)
        emps = emp_obj.browse(cr, uid, emp_ids, context)
        seq = 0
        for emp in emps:
            for day_dt in days:
                day = day_dt.strftime('%Y-%m-%d')
                #if there is no working time defined to employee then continue to next employee directly
                if not emp.calendar_id or not emp.calendar_id.attendance_ids:
                    seq += 1
                    '''
                    init a new empty line by employee/day without period info
                    '''
                    rpt_line = {
                        'seq': seq,
                        'emp_id': emp.id,
                        'day': day,
                        'period_id': None,
                        'sign_in': None,
                        'sign_out': None,
                        'hours_normal': None,
                        'hours_ot': None,
                        'is_late': False,
                        'is_early': False,
                        'is_absent': False,
                        'hours_normal2': None,
                        'hours_ot2': None,
                    }
                    rpt_lns.append(rpt_line)
                    continue
                for period in emp.calendar_id.attendance_ids:
                    if day_dt.isoweekday() != (int(period.dayofweek) + 1):
                        continue
                    '''
                    init a new empty line by employee/day/period
                    '''
                    seq += 1
                    rpt_line = {
                        'seq': seq,
                        'emp_id': emp.id,
                        'day': day,
                        'period_id': period.id,
                        'sign_in': None,
                        'sign_out': None,
                        'hours_normal': None,
                        'hours_ot': None,
                        'is_late': False,
                        'is_early': False,
                        'is_absent': False,
                        'hours_normal2': None,
                        'hours_ot2': None,
                    }
                    rpt_lns.append(rpt_line)
                    #find the normal attendance by employee/day/period
                    attend_key = '%s-%s-%s' % (emp.id, day, period.id)
                    attend = attends_normal.get(attend_key, False)
                    if attend:
                        #found the normal attendance, with sign in and out record, put the data directly
                        hour_in = attend[
                            'in_time'].hour + attend['in_time'].minute / 60.0
                        hour_out = attend[
                            'out_time'].hour + attend['out_time'].minute / 60.0
                        hours_valid = hour_out - hour_in - period.hours_non_work
                        attend_hours = self._attend_hours(hours_valid, period)
                        rpt_line.update({
                            'period_id': period.id,
                            'sign_in': hour_in,
                            'sign_out': hour_out,
                            'hours_normal': attend_hours[0],
                            'hours_ot': attend_hours[1],
                            'is_late': attend['in_action'] == 'sign_in_late',
                            'is_early':
                            attend['out_action'] == 'sign_out_early',
                            'hours_normal2': attend_hours[2],
                            'hours_ot2': attend_hours[3],
                        })
                        continue
                    #the abnormal attendance, with sign in or out record only, or without any attendance
                    attend_ids = attend_obj.search(
                        cr,
                        uid,
                        [('employee_id', '=', emp.id), ('day', '=', day),
                         ('cale_period_id', '=', period.id),
                         ('action', 'in', ('sign_in', 'sign_in_late',
                                           'sign_out', 'sign_out_early'))],
                        context=context)
                    if attend_ids:
                        #found sign in or sign out data, there shoule be only one record, so use the first ID to get data
                        attend = attend_obj.browse(cr,
                                                   uid,
                                                   attend_ids[0],
                                                   context=context)
                        attend_time = fields.datetime.context_timestamp(
                            cr, uid,
                            datetime.strptime(attend.name,
                                              DEFAULT_SERVER_DATETIME_FORMAT),
                            context)
                        hour_in = None
                        hour_out = None
                        hours_valid = None
                        hours_normal = None
                        hours_ot = None
                        is_late = False
                        is_early = False
                        is_absent = False
                        hours_normal2 = None
                        hours_ot2 = None
                        #Only have sign in record
                        if attend.action in ('sign_in', 'sign_in_late'):
                            hour_in = attend_time.hour + attend_time.minute / 60.0
                            if emp.calendar_id.no_out_option == 'early':
                                #treat as leave early
                                if not period.is_full_ot:
                                    is_early = True
                                hours_valid = period.hour_to - hour_in - period.hours_non_work - emp.calendar_id.no_out_time / 60.0
                            else:
                                #treat as absent
                                if not period.is_full_ot:
                                    is_absent = True
                                hours_valid = 0.0
                        #Only have sign out record
                        if attend.action in ('sign_out', 'sign_out_early'):
                            hour_out = attend_time.hour + attend_time.minute / 60.0
                            if emp.calendar_id.no_in_option == 'late':
                                #treat as leave early
                                if not period.is_full_ot:
                                    is_late = True
                                hours_valid = hour_out - period.hour_from - period.hours_non_work - emp.calendar_id.no_in_time / 60.0
                            else:
                                #treat as absent
                                if not period.is_full_ot:
                                    is_absent = True
                                hours_valid = 0.0
                        if hours_valid:
                            hours_normal, hours_ot, hours_normal2, hours_ot2 = self._attend_hours(
                                hours_valid, period)

                        rpt_line.update({
                            'period_id': period.id,
                            'sign_in': hour_in,
                            'sign_out': hour_out,
                            'hours_normal': hours_normal,
                            'hours_ot': hours_ot,
                            'is_late': is_late,
                            'is_early': is_early,
                            'is_absent': is_absent,
                            'hours_normal2': hours_normal2,
                            'hours_ot2': hours_ot2,
                        })
                    else:
                        if not period.is_full_ot:
                            rpt_line.update({'is_absent': True})
        '''========return data to rpt_base.run_report()========='''
        return self.pool.get('hr.rpt.attend.emp.day.line'), rpt_lns

    def _pdf_data(self, cr, uid, ids, form_data, context=None):
        return {'xmlrpt_name': 'hr.rpt.attend.emp.day'}
Exemplo n.º 11
0
class Post(osv.Model):
    _name = 'forum.post'
    _description = 'Forum Post'
    _inherit = ['mail.thread', 'website.seo.metadata']
    _order = "is_correct DESC, vote_count DESC, write_date DESC"

    def _get_user_vote(self, cr, uid, ids, field_name, arg, context):
        res = dict.fromkeys(ids, 0)
        vote_ids = self.pool['forum.post.vote'].search(cr,
                                                       uid,
                                                       [('post_id', 'in', ids),
                                                        ('user_id', '=', uid)],
                                                       context=context)
        for vote in self.pool['forum.post.vote'].browse(cr,
                                                        uid,
                                                        vote_ids,
                                                        context=context):
            res[vote.post_id.id] = vote.vote
        return res

    def _get_vote_count(self, cr, uid, ids, field_name, arg, context):
        res = dict.fromkeys(ids, 0)
        for post in self.browse(cr, uid, ids, context=context):
            for vote in post.vote_ids:
                res[post.id] += int(vote.vote)
        return res

    def _get_post_from_vote(self, cr, uid, ids, context=None):
        result = {}
        for vote in self.pool['forum.post.vote'].browse(cr,
                                                        uid,
                                                        ids,
                                                        context=context):
            result[vote.post_id.id] = True
        return result.keys()

    def _get_user_favourite(self, cr, uid, ids, field_name, arg, context):
        res = dict.fromkeys(ids, False)
        for post in self.browse(cr, uid, ids, context=context):
            if uid in [f.id for f in post.favourite_ids]:
                res[post.id] = True
        return res

    def _get_favorite_count(self, cr, uid, ids, field_name, arg, context):
        res = dict.fromkeys(ids, 0)
        for post in self.browse(cr, uid, ids, context=context):
            res[post.id] += len(post.favourite_ids)
        return res

    def _get_post_from_hierarchy(self, cr, uid, ids, context=None):
        post_ids = set(ids)
        for post in self.browse(cr, SUPERUSER_ID, ids, context=context):
            if post.parent_id:
                post_ids.add(post.parent_id.id)
        return list(post_ids)

    def _get_child_count(self,
                         cr,
                         uid,
                         ids,
                         field_name=False,
                         arg={},
                         context=None):
        res = dict.fromkeys(ids, 0)
        for post in self.browse(cr, uid, ids, context=context):
            if post.parent_id:
                res[post.parent_id.id] = len(post.parent_id.child_ids)
            else:
                res[post.id] = len(post.child_ids)
        return res

    def _get_uid_answered(self, cr, uid, ids, field_name, arg, context=None):
        res = dict.fromkeys(ids, False)
        for post in self.browse(cr, uid, ids, context=context):
            res[post.id] = any(answer.create_uid.id == uid
                               for answer in post.child_ids)
        return res

    def _get_has_validated_answer(self,
                                  cr,
                                  uid,
                                  ids,
                                  field_name,
                                  arg,
                                  context=None):
        res = dict.fromkeys(ids, False)
        ans_ids = self.search(cr,
                              uid, [('parent_id', 'in', ids),
                                    ('is_correct', '=', True)],
                              context=context)
        for answer in self.browse(cr, uid, ans_ids, context=context):
            res[answer.parent_id.id] = True
        return res

    def _is_self_reply(self, cr, uid, ids, field_name, arg, context=None):
        res = dict.fromkeys(ids, False)
        for post in self.browse(cr, uid, ids, context=context):
            res[post.
                id] = post.parent_id and post.parent_id.create_uid == post.create_uid or False
        return res

    def _get_post_karma_rights(self,
                               cr,
                               uid,
                               ids,
                               field_name,
                               arg,
                               context=None):
        user = self.pool['res.users'].browse(cr, uid, uid, context=context)
        res = dict.fromkeys(ids, False)
        for post in self.browse(cr, uid, ids, context=context):
            res[post.id] = {
                'karma_ask':
                post.forum_id.karma_ask,
                'karma_answer':
                post.forum_id.karma_answer,
                'karma_accept':
                post.parent_id and post.parent_id.create_uid.id == uid
                and post.forum_id.karma_answer_accept_own
                or post.forum_id.karma_answer_accept_all,
                'karma_edit':
                post.create_uid.id == uid and post.forum_id.karma_edit_own
                or post.forum_id.karma_edit_all,
                'karma_close':
                post.create_uid.id == uid and post.forum_id.karma_close_own
                or post.forum_id.karma_close_all,
                'karma_unlink':
                post.create_uid.id == uid and post.forum_id.karma_unlink_own
                or post.forum_id.karma_unlink_all,
                'karma_upvote':
                post.forum_id.karma_upvote,
                'karma_downvote':
                post.forum_id.karma_downvote,
                'karma_comment':
                post.create_uid.id == uid and post.forum_id.karma_comment_own
                or post.forum_id.karma_comment_all,
                'karma_comment_convert':
                post.create_uid.id == uid
                and post.forum_id.karma_comment_convert_own
                or post.forum_id.karma_comment_convert_all,
            }
            res[post.id].update({
                'can_ask':
                uid == SUPERUSER_ID or user.karma >= res[post.id]['karma_ask'],
                'can_answer':
                uid == SUPERUSER_ID
                or user.karma >= res[post.id]['karma_answer'],
                'can_accept':
                uid == SUPERUSER_ID
                or user.karma >= res[post.id]['karma_accept'],
                'can_edit':
                uid == SUPERUSER_ID
                or user.karma >= res[post.id]['karma_edit'],
                'can_close':
                uid == SUPERUSER_ID
                or user.karma >= res[post.id]['karma_close'],
                'can_unlink':
                uid == SUPERUSER_ID
                or user.karma >= res[post.id]['karma_unlink'],
                'can_upvote':
                uid == SUPERUSER_ID
                or user.karma >= res[post.id]['karma_upvote'],
                'can_downvote':
                uid == SUPERUSER_ID
                or user.karma >= res[post.id]['karma_downvote'],
                'can_comment':
                uid == SUPERUSER_ID
                or user.karma >= res[post.id]['karma_comment'],
                'can_comment_convert':
                uid == SUPERUSER_ID
                or user.karma >= res[post.id]['karma_comment_convert'],
            })
        return res

    _columns = {
        'name':
        fields.char('Title'),
        'forum_id':
        fields.many2one('forum.forum', 'Forum', required=True),
        'content':
        fields.html('Content'),
        'tag_ids':
        fields.many2many('forum.tag', 'forum_tag_rel', 'forum_id',
                         'forum_tag_id', 'Tags'),
        'state':
        fields.selection([('active', 'Active'), ('close', 'Close'),
                          ('offensive', 'Offensive')], 'Status'),
        'views':
        fields.integer('Number of Views'),
        'active':
        fields.boolean('Active'),
        'is_correct':
        fields.boolean(
            'Valid Answer',
            help='Correct Answer or Answer on this question accepted.'),
        'website_message_ids':
        fields.one2many(
            'mail.message',
            'res_id',
            domain=lambda self: [
                '&', ('model', '=', self._name),
                ('type', 'in', ['email', 'comment'])
            ],
            string='Post Messages',
            help="Comments on forum post",
        ),
        # history
        'create_date':
        fields.datetime('Asked on', select=True, readonly=True),
        'create_uid':
        fields.many2one('res.users', 'Created by', select=True, readonly=True),
        'write_date':
        fields.datetime('Update on', select=True, readonly=True),
        'write_uid':
        fields.many2one('res.users', 'Updated by', select=True, readonly=True),
        # vote fields
        'vote_ids':
        fields.one2many('forum.post.vote', 'post_id', 'Votes'),
        'user_vote':
        fields.function(_get_user_vote, string='My Vote', type='integer'),
        'vote_count':
        fields.function(_get_vote_count,
                        string="Votes",
                        type='integer',
                        store={
                            'forum.post':
                            (lambda self, cr, uid, ids, c={}: ids,
                             ['vote_ids'], 10),
                            'forum.post.vote': (_get_post_from_vote, [], 10),
                        }),
        # favorite fields
        'favourite_ids':
        fields.many2many('res.users', string='Favourite'),
        'user_favourite':
        fields.function(_get_user_favourite,
                        string="My Favourite",
                        type='boolean'),
        'favourite_count':
        fields.function(_get_favorite_count,
                        string='Favorite Count',
                        type='integer',
                        store={
                            'forum.post':
                            (lambda self, cr, uid, ids, c={}: ids,
                             ['favourite_ids'], 10),
                        }),
        # hierarchy
        'parent_id':
        fields.many2one('forum.post', 'Question', ondelete='cascade'),
        'self_reply':
        fields.function(_is_self_reply,
                        'Reply to own question',
                        type='boolean',
                        store={
                            'forum.post':
                            (lambda self, cr, uid, ids, c={}: ids,
                             ['parent_id', 'create_uid'], 10),
                        }),
        'child_ids':
        fields.one2many('forum.post', 'parent_id', 'Answers'),
        'child_count':
        fields.function(_get_child_count,
                        string="Answers",
                        type='integer',
                        store={
                            'forum.post': (_get_post_from_hierarchy,
                                           ['parent_id', 'child_ids'], 10),
                        }),
        'uid_has_answered':
        fields.function(
            _get_uid_answered,
            string='Has Answered',
            type='boolean',
        ),
        'has_validated_answer':
        fields.function(_get_has_validated_answer,
                        string='Has a Validated Answered',
                        type='boolean',
                        store={
                            'forum.post':
                            (_get_post_from_hierarchy,
                             ['parent_id', 'child_ids', 'is_correct'], 10),
                        }),
        # closing
        'closed_reason_id':
        fields.many2one('forum.post.reason', 'Reason'),
        'closed_uid':
        fields.many2one('res.users', 'Closed by', select=1),
        'closed_date':
        fields.datetime('Closed on', readonly=True),
        # karma
        'karma_ask':
        fields.function(_get_post_karma_rights,
                        string='Karma to ask',
                        type='integer',
                        multi='_get_post_karma_rights'),
        'karma_answer':
        fields.function(_get_post_karma_rights,
                        string='Karma to answer',
                        type='integer',
                        multi='_get_post_karma_rights'),
        'karma_accept':
        fields.function(_get_post_karma_rights,
                        string='Karma to accept this answer',
                        type='integer',
                        multi='_get_post_karma_rights'),
        'karma_edit':
        fields.function(_get_post_karma_rights,
                        string='Karma to edit',
                        type='integer',
                        multi='_get_post_karma_rights'),
        'karma_close':
        fields.function(_get_post_karma_rights,
                        string='Karma to close',
                        type='integer',
                        multi='_get_post_karma_rights'),
        'karma_unlink':
        fields.function(_get_post_karma_rights,
                        string='Karma to unlink',
                        type='integer',
                        multi='_get_post_karma_rights'),
        'karma_upvote':
        fields.function(_get_post_karma_rights,
                        string='Karma to upvote',
                        type='integer',
                        multi='_get_post_karma_rights'),
        'karma_downvote':
        fields.function(_get_post_karma_rights,
                        string='Karma to downvote',
                        type='integer',
                        multi='_get_post_karma_rights'),
        'karma_comment':
        fields.function(_get_post_karma_rights,
                        string='Karma to comment',
                        type='integer',
                        multi='_get_post_karma_rights'),
        'karma_comment_convert':
        fields.function(_get_post_karma_rights,
                        string='karma to convert as a comment',
                        type='integer',
                        multi='_get_post_karma_rights'),
        # access rights
        'can_ask':
        fields.function(_get_post_karma_rights,
                        string='Can Ask',
                        type='boolean',
                        multi='_get_post_karma_rights'),
        'can_answer':
        fields.function(_get_post_karma_rights,
                        string='Can Answer',
                        type='boolean',
                        multi='_get_post_karma_rights'),
        'can_accept':
        fields.function(_get_post_karma_rights,
                        string='Can Accept',
                        type='boolean',
                        multi='_get_post_karma_rights'),
        'can_edit':
        fields.function(_get_post_karma_rights,
                        string='Can Edit',
                        type='boolean',
                        multi='_get_post_karma_rights'),
        'can_close':
        fields.function(_get_post_karma_rights,
                        string='Can Close',
                        type='boolean',
                        multi='_get_post_karma_rights'),
        'can_unlink':
        fields.function(_get_post_karma_rights,
                        string='Can Unlink',
                        type='boolean',
                        multi='_get_post_karma_rights'),
        'can_upvote':
        fields.function(_get_post_karma_rights,
                        string='Can Upvote',
                        type='boolean',
                        multi='_get_post_karma_rights'),
        'can_downvote':
        fields.function(_get_post_karma_rights,
                        string='Can Downvote',
                        type='boolean',
                        multi='_get_post_karma_rights'),
        'can_comment':
        fields.function(_get_post_karma_rights,
                        string='Can Comment',
                        type='boolean',
                        multi='_get_post_karma_rights'),
        'can_comment_convert':
        fields.function(_get_post_karma_rights,
                        string='Can Convert to Comment',
                        type='boolean',
                        multi='_get_post_karma_rights'),
    }

    _defaults = {
        'state': 'active',
        'views': 0,
        'active': True,
        'vote_ids': list(),
        'favourite_ids': list(),
        'child_ids': list(),
    }

    def create(self, cr, uid, vals, context=None):
        if context is None:
            context = {}
        create_context = dict(context, mail_create_nolog=True)
        post_id = super(Post, self).create(cr,
                                           uid,
                                           vals,
                                           context=create_context)
        post = self.browse(
            cr, SUPERUSER_ID, post_id, context=context
        )  # SUPERUSER_ID to avoid read access rights issues when creating
        # karma-based access
        if post.parent_id and not post.can_ask:
            raise KarmaError('Not enough karma to create a new question')
        elif not post.parent_id and not post.can_answer:
            raise KarmaError('Not enough karma to answer to a question')
        # messaging and chatter
        base_url = self.pool['ir.config_parameter'].get_param(
            cr, uid, 'web.base.url')
        if post.parent_id:
            body = _(
                '<p>A new answer for <i>%s</i> has been posted. <a href="%s/forum/%s/question/%s">Click here to access the post.</a></p>'
                % (post.parent_id.name, base_url, slug(
                    post.parent_id.forum_id), slug(post.parent_id)))
            self.message_post(cr,
                              uid,
                              post.parent_id.id,
                              subject=_('Re: %s') % post.parent_id.name,
                              body=body,
                              subtype='website_forum.mt_answer_new',
                              context=context)
        else:
            body = _(
                '<p>A new question <i>%s</i> has been asked on %s. <a href="%s/forum/%s/question/%s">Click here to access the question.</a></p>'
                % (post.name, post.forum_id.name, base_url, slug(
                    post.forum_id), slug(post)))
            self.message_post(cr,
                              uid,
                              post_id,
                              subject=post.name,
                              body=body,
                              subtype='website_forum.mt_question_new',
                              context=context)
            self.pool['res.users'].add_karma(
                cr,
                SUPERUSER_ID, [uid],
                post.forum_id.karma_gen_question_new,
                context=context)
        return post_id

    def write(self, cr, uid, ids, vals, context=None):
        posts = self.browse(cr, uid, ids, context=context)
        if 'state' in vals:
            if vals['state'] in ['active', 'close'] and any(not post.can_close
                                                            for post in posts):
                raise KarmaError('Not enough karma to close or reopen a post.')
        if 'active' in vals:
            if any(not post.can_unlink for post in posts):
                raise KarmaError(
                    'Not enough karma to delete or reactivate a post')
        if 'is_correct' in vals:
            if any(not post.can_accept for post in posts):
                raise KarmaError(
                    'Not enough karma to accept or refuse an answer')
            # update karma except for self-acceptance
            mult = 1 if vals['is_correct'] else -1
            for post in self.browse(cr, uid, ids, context=context):
                if vals['is_correct'] != post.is_correct and post.create_uid.id != uid:
                    self.pool['res.users'].add_karma(
                        cr,
                        SUPERUSER_ID, [post.create_uid.id],
                        post.forum_id.karma_gen_answer_accepted * mult,
                        context=context)
                    self.pool['res.users'].add_karma(
                        cr,
                        SUPERUSER_ID, [uid],
                        post.forum_id.karma_gen_answer_accept * mult,
                        context=context)
        if any(key not in [
                'state', 'active', 'is_correct', 'closed_uid', 'closed_date',
                'closed_reason_id'
        ] for key in vals.keys()) and any(not post.can_edit for post in posts):
            raise KarmaError('Not enough karma to edit a post.')

        res = super(Post, self).write(cr, uid, ids, vals, context=context)
        # if post content modify, notify followers
        if 'content' in vals or 'name' in vals:
            for post in posts:
                if post.parent_id:
                    body, subtype = _(
                        'Answer Edited'), 'website_forum.mt_answer_edit'
                    obj_id = post.parent_id.id
                else:
                    body, subtype = _(
                        'Question Edited'), 'website_forum.mt_question_edit'
                    obj_id = post.id
                self.message_post(cr,
                                  uid,
                                  obj_id,
                                  body=body,
                                  subtype=subtype,
                                  context=context)
        return res

    def close(self, cr, uid, ids, reason_id, context=None):
        if any(post.parent_id
               for post in self.browse(cr, uid, ids, context=context)):
            return False
        return self.pool['forum.post'].write(
            cr,
            uid,
            ids, {
                'state':
                'close',
                'closed_uid':
                uid,
                'closed_date':
                datetime.today().strftime(
                    tools.DEFAULT_SERVER_DATETIME_FORMAT),
                'closed_reason_id':
                reason_id,
            },
            context=context)

    def unlink(self, cr, uid, ids, context=None):
        posts = self.browse(cr, uid, ids, context=context)
        if any(not post.can_unlink for post in posts):
            raise KarmaError('Not enough karma to unlink a post')
        # if unlinking an answer with accepted answer: remove provided karma
        for post in posts:
            if post.is_correct:
                self.pool['res.users'].add_karma(
                    cr,
                    SUPERUSER_ID, [post.create_uid.id],
                    post.forum_id.karma_gen_answer_accepted * -1,
                    context=context)
                self.pool['res.users'].add_karma(
                    cr,
                    SUPERUSER_ID, [uid],
                    post.forum_id.karma_gen_answer_accept * -1,
                    context=context)
        return super(Post, self).unlink(cr, uid, ids, context=context)

    def vote(self, cr, uid, ids, upvote=True, context=None):
        posts = self.browse(cr, uid, ids, context=context)

        if upvote and any(not post.can_upvote for post in posts):
            raise KarmaError('Not enough karma to upvote.')
        elif not upvote and any(not post.can_downvote for post in posts):
            raise KarmaError('Not enough karma to downvote.')

        Vote = self.pool['forum.post.vote']
        vote_ids = Vote.search(cr,
                               uid, [('post_id', 'in', ids),
                                     ('user_id', '=', uid)],
                               context=context)
        new_vote = '1' if upvote else '-1'
        voted_forum_ids = set()
        if vote_ids:
            for vote in Vote.browse(cr, uid, vote_ids, context=context):
                if upvote:
                    new_vote = '0' if vote.vote == '-1' else '1'
                else:
                    new_vote = '0' if vote.vote == '1' else '-1'
                Vote.write(cr,
                           uid,
                           vote_ids, {'vote': new_vote},
                           context=context)
                voted_forum_ids.add(vote.post_id.id)
        for post_id in set(ids) - voted_forum_ids:
            for post_id in ids:
                Vote.create(cr,
                            uid, {
                                'post_id': post_id,
                                'vote': new_vote
                            },
                            context=context)
        return {
            'vote_count':
            self._get_vote_count(cr, uid, ids, None, None,
                                 context=context)[ids[0]],
            'user_vote':
            new_vote
        }

    def convert_answer_to_comment(self, cr, uid, id, context=None):
        """ Tools to convert an answer (forum.post) to a comment (mail.message).
        The original post is unlinked and a new comment is posted on the question
        using the post create_uid as the comment's author. """
        post = self.browse(cr, SUPERUSER_ID, id, context=context)
        if not post.parent_id:
            return False

        # karma-based action check: use the post field that computed own/all value
        if not post.can_comment_convert:
            raise KarmaError(
                'Not enough karma to convert an answer to a comment')

        # post the message
        question = post.parent_id
        values = {
            'author_id': post.create_uid.partner_id.id,
            'body': html2plaintext(post.content),
            'type': 'comment',
            'subtype': 'mail.mt_comment',
            'date': post.create_date,
        }
        message_id = self.pool['forum.post'].message_post(
            cr,
            uid,
            question.id,
            context=dict(context, mail_create_nosubcribe=True),
            **values)

        # unlink the original answer, using SUPERUSER_ID to avoid karma issues
        self.pool['forum.post'].unlink(cr,
                                       SUPERUSER_ID, [post.id],
                                       context=context)

        return message_id

    def convert_comment_to_answer(self,
                                  cr,
                                  uid,
                                  message_id,
                                  default=None,
                                  context=None):
        """ Tool to convert a comment (mail.message) into an answer (forum.post).
        The original comment is unlinked and a new answer from the comment's author
        is created. Nothing is done if the comment's author already answered the
        question. """
        comment = self.pool['mail.message'].browse(cr,
                                                   SUPERUSER_ID,
                                                   message_id,
                                                   context=context)
        post = self.pool['forum.post'].browse(cr,
                                              uid,
                                              comment.res_id,
                                              context=context)
        user = self.pool['res.users'].browse(cr, uid, uid, context=context)
        if not comment.author_id or not comment.author_id.user_ids:  # only comment posted by users can be converted
            return False

        # karma-based action check: must check the message's author to know if own / all
        karma_convert = comment.author_id.id == user.partner_id.id and post.forum_id.karma_comment_convert_own or post.forum_id.karma_comment_convert_all
        can_convert = uid == SUPERUSER_ID or user.karma >= karma_convert
        if not can_convert:
            raise KarmaError(
                'Not enough karma to convert a comment to an answer')

        # check the message's author has not already an answer
        question = post.parent_id if post.parent_id else post
        post_create_uid = comment.author_id.user_ids[0]
        if any(answer.create_uid.id == post_create_uid.id
               for answer in question.child_ids):
            return False

        # create the new post
        post_values = {
            'forum_id': question.forum_id.id,
            'content': comment.body,
            'parent_id': question.id,
        }
        # done with the author user to have create_uid correctly set
        new_post_id = self.pool['forum.post'].create(cr,
                                                     post_create_uid.id,
                                                     post_values,
                                                     context=context)

        # delete comment
        self.pool['mail.message'].unlink(cr,
                                         SUPERUSER_ID, [comment.id],
                                         context=context)

        return new_post_id

    def unlink_comment(self, cr, uid, id, message_id, context=None):
        comment = self.pool['mail.message'].browse(cr,
                                                   SUPERUSER_ID,
                                                   message_id,
                                                   context=context)
        post = self.pool['forum.post'].browse(cr, uid, id, context=context)
        user = self.pool['res.users'].browse(cr,
                                             SUPERUSER_ID,
                                             uid,
                                             context=context)
        if not comment.model == 'forum.post' or not comment.res_id == id:
            return False

        # karma-based action check: must check the message's author to know if own or all
        karma_unlink = comment.author_id.id == user.partner_id.id and post.forum_id.karma_comment_unlink_own or post.forum_id.karma_comment_unlink_all
        can_unlink = uid == SUPERUSER_ID or user.karma >= karma_unlink
        if not can_unlink:
            raise KarmaError('Not enough karma to unlink a comment')

        return self.pool['mail.message'].unlink(cr,
                                                SUPERUSER_ID, [message_id],
                                                context=context)

    def set_viewed(self, cr, uid, ids, context=None):
        cr.execute("""UPDATE forum_post SET views = views+1 WHERE id IN %s""",
                   (tuple(ids), ))
        return True

    def _get_access_link(self, cr, uid, mail, partner, context=None):
        post = self.pool['forum.post'].browse(cr,
                                              uid,
                                              mail.res_id,
                                              context=context)
        res_id = post.parent_id and "%s#answer-%s" % (post.parent_id.id,
                                                      post.id) or post.id
        return "/forum/%s/question/%s" % (post.forum_id.id, res_id)
Exemplo n.º 12
0
class ProductionPlan(osv.osv):
    _inherit = 'production.plan'
    _columns = {
        'plan_list': fields.one2many('production.plan.list', 'plan_id', 'Production Plan List', readonly=True),
    }

    def compute(self, cr, uid, ids, context=None):
        val = self.browse(cr, uid, ids, context={})[0]
        product_obj = self.pool.get('product.product')
        def _create_list(ID,name,product,qty):
            self.pool.get('production.plan.list').create(cr,uid,{'plan_id':ID,'name':name,'product_id': product.id,'qty': qty,'ean13':product.ean13 or ''})
        if val.plan_line:
            for x in val.plan_line:
                plan = x.plan
                if x.real - x.total == 0 :
                    plan = x.max
                elif x.real - x.total <= 0 :
                    plan = abs(x.real - x.total) + x.max
                elif x.real - x.total < x.min:
                    plan = x.max - (x.real - x.total)
                self.pool.get('production.plan.line').write(cr, uid, [x.id], {'plan': plan, 'end': x.real - x.total + plan})
        else:
            product = []
            list_product = []
            for x in val.order_ids:
                for l in x.order_line:
                    product.append({'product_id': l.product_id.id, 'line': l, 'qty': l.product_uom_qty, 'uom': l.product_uom.id})
                    _create_list(val.id,x.name,l.product_id,l.product_uom_qty)
            for x in val.stock_ids:
                for l in x.stock_line:
                    product.append({'source':x.name,'product_id': l.product_id.id, 'line': l, 'qty': l.product_qty, 'uom': l.product_uom.id})
                    _create_list(val.id,x.name,l.product_id,l.product_qty)
            for x in val.stockw_ids:
                for l in x.stock_line:
                    product.append({'product_id': l.product_id.id, 'line': l, 'qty': l.product_qty, 'uom': l.product_uom.id})

            data = {}
            for p in product:
                data[p['product_id']] = {'qty': [], 'uom': p['uom'], 'line': []}
            for p in product:
                data[p['product_id']]['qty'].append(p['qty'])
                data[p['product_id']]['line'].append(p['line'])
            for i in data:
                order = sum(data[i]['qty'])
                brg = product_obj.browse(cr, uid, i)
                min = 0; max = 0; plan = order
                sid = self.pool.get('stock.warehouse.orderpoint').search(cr, uid, [('product_id', '=', i)])
                if sid:
                    sto = self.pool.get('stock.warehouse.orderpoint').browse(cr, uid, sid)[0]
                    min = sto.product_min_qty
                    max = sto.product_max_qty
                    plan = 0
                    if brg.qty_available - order == 0 :
                        plan = max
                    elif brg.qty_available - order <= 0 :
                        plan = abs(brg.qty_available - order) + max
                    elif brg.qty_available - order < min:
                        plan = max - (brg.qty_available - order)
                self.pool.get('production.plan.line').create(cr, uid, {
                                                                   'plan_id': val.id,
                                                                   'product_id': i,
                                                                   'product_uom': data[i]['uom'],
                                                                   'total': order,
                                                                   'name': product_obj.name_get(cr, uid, [i])[0][1],
                                                                   'real': brg.qty_available,
                                                                   'min': min,
                                                                   'max': max,
                                                                   'plan': plan,
                                                                   'end': brg.qty_available - order + plan 
                                                                   })
        return True 
Exemplo n.º 13
0
class mrp_barcode_setting(osv.osv):
    _name = 'mrp.barcode.setting'

    def compose_barcode(self, cr, uid, ids, context=None):
        vals = self.browse(cr,uid,ids[0],)
        content1 = []    
        content2 =[]    
        content3 = []    
        Ap4 = {'1':12,'2':'16'}
        Y1=0
        Y23=0
        list_obj = self.pool.get('mrp.barcode.setting.list')
        ul = [i.id for i in vals.result_ids]
        if ul :
            list_obj.unlink(cr, uid, ul , context=context)
        def construct_label(A,X,Y,R):
            return "\n"+",".join([A+X,Y,R,'1,1,1,N,'])
        def construct_barcode(B,X,Y,R,T,H):
            return "\n"+",".join([B+X,Y,R,T,'2,2',H,'N,'])
        if vals.detail_ids:
            for l in vals.detail_ids:
                if l.type == "A":
                    Y1+=int(Ap4[l.size])
                    str1 = construct_label("A",str(vals.initX1),str(Y1),l.rotation)
                else :
                    Y1+=int(l.height)+4
                    str1 = construct_barcode("B",str(vals.initX1),str(Y1),l.rotation,l.barcode,str(l.height))
                list_obj.create(cr,uid,{'setting_id':ids[0],'type' :l.type,'kolom':1,'list':str1})
        if vals.detail_ids2:
            for l in vals.detail_ids2:
                if l.type == "A":
                    str2 = construct_label("A",str(vals.initX2),str(Y23),l.rotation)
                    str3 = construct_label("A",str(vals.initX3),str(Y23),l.rotation)
                    Y23+=int(Ap4[l.size])
                else :
                    str2 = construct_barcode("B",str(vals.initX2),str(Y23),l.rotation,l.barcode,str(l.height))
                    str3 = construct_barcode("B",str(vals.initX3),str(Y23),l.rotation,l.barcode,str(l.height))
                    Y23+=int(l.height)+4
                list_obj.create(cr,uid,{'setting_id':ids[0],'type' :l.type,'kolom':2,'list':str2})
                list_obj.create(cr,uid,{'setting_id':ids[0],'type' :l.type,'kolom':3,'list':str3})
        return True

    _columns = {
        'name'      : fields.char('Name',size=10),
        'detail_ids2': fields.one2many('mrp.barcode.setting.line2','setting_id',string='Setting'),
        'detail_ids': fields.one2many('mrp.barcode.setting.line','setting_id',string='Setting'),
        'deltaY'    : fields.integer('Delta Y',size=3),
        'initX1'    : fields.integer('X0 column 1',size=3),
        'initX2'    : fields.integer('X0 column 2',size=3),
        'initX3'    : fields.integer('X0 column 3',size=3),
        'result_ids':fields.one2many('mrp.barcode.setting.list','setting_id',string='Setting',readonly=True),
        'active'    :fields.boolean("Active"),
        'initRX'    : fields.integer('X0 Form',size=3),
        'initRY'    : fields.integer('Y0 Form',size=3),
    }

    _defaults = {
        'deltaY'   :145,
        'initX1'    : 240,
        'initX2'    : 270,
        'initX3'    : 550,
        'active'    : True,
        'initRX'    : 0,
        'initRY'    : 0,
    }
Exemplo n.º 14
0
class ebay_user(osv.osv):
    _name = "ebay.user"
    _description = "a registered eBay user"

    @staticmethod
    def get_shipping_service_type():
        return [
            ('cnam', _('China Post Normal Air Mail')),
            ('cnram', _('China Post Registered Air Mail')),
            ('hkam', _('HongKong Post Normal Air Mail')),
            ('hkram', _('HongKong Post Registered Air Mail')),
            ('sgam', _('Sing Post Normal Air Mail')),
            ('sgram', _('Sing Post Registered Air Mail')),
        ]

    def _get_shipping_service_type(self, cr, uid, context=None):
        return self.get_shipping_service_type()

    _columns = {
        'email':
        fields.char('Email', size=128, readonly=True),
        'feedback_rating_star':
        fields.selection(
            [('Blue', 'Blue Star'),
             ('CustomCode', 'Reserved for internal or future use.'),
             ('Green', 'Green Star'), ('GreenShooting', 'Green Shooting Star'),
             ('None', 'No graphic displayed'), ('Purple', 'Purple Star'),
             ('PurpleShooting', 'Purple Shooting Star'), ('Red', 'Red Star'),
             ('RedShooting', 'Red Shooting Star'),
             ('SilverShooting', 'Silver Shooting Star'),
             ('Turquoise', 'Turquoise Star'),
             ('TurquoiseShooting', 'Turquoise Shooting Star'),
             ('Yellow', 'Yellow Star'),
             ('YellowShooting', 'Yellow Shooting Star')],
            'Feedback Rating Star',
            readonly=True),
        'feedback_score':
        fields.integer('Feedback Score', readonly=True),
        'positive_feedback_percent':
        fields.float('Feedback Percent', readonly=True),
        'registration_date':
        fields.datetime('Registration Date', readonly=True),
        'store_owner':
        fields.boolean('Store Owner', readonly=True),
        'store_site':
        fields.char('Store Site', readonly=True),
        'store_url':
        fields.char('Store URL', readonly=True),
        'top_rated_seller':
        fields.boolean('Top-rated Seller', readonly=True),
        'site':
        fields.char('Site', readonly=True),
        'unique_negative_feedback_count':
        fields.integer('Negative', readonly=True),
        'unique_neutral_feedback_count':
        fields.integer('Neutral', readonly=True),
        'unique_positive_feedback_count':
        fields.integer('Positive', readonly=True),
        'name':
        fields.char('User ID', required=True, select=True),
        # Selleris
        'seller_list_ids':
        fields.one2many('ebay.seller.list',
                        'user_id',
                        'Seller Lists',
                        readonly=True),
        'last_updated':
        fields.datetime('Last Updated'),
        # Application keys for authorization
        'ownership':
        fields.boolean('Ownership', readonly=True),
        'sandbox':
        fields.boolean('Sandbox'),
        'sale_site':
        fields.selection([
            ('0', 'US'),
            ('2', 'Canada'),
            ('3', 'UK'),
            ('15', 'Australia'),
            ('201', 'HongKong'),
        ], 'Sale Site'),
        'app_id':
        fields.char('AppID', size=64),
        'dev_id':
        fields.char('DevID', size=64),
        'cert':
        fields.char('CERT', size=64),
        'ru_name':
        fields.char('RuName', size=64),
        # Auth info, get from FetchToken
        'ebay_auth_token':
        fields.char('eBayAuthToken', readonly=True),
        'hard_expiration_time':
        fields.datetime('HardExpirationTime', readonly=True),
        'rest_token':
        fields.char('RESTToken', readonly=True),
        # Sale status
        'monthly_sales':
        fields.float('Monthly Sales', readonly=True),
        'monthly_sales_volume':
        fields.integer('Monthly Sales Volume', readonly=True),
        # Additional Info
        'ebay_item_ids':
        fields.one2many('ebay.item', 'ebay_user_id', 'Items'),
        'paypal_email_address':
        fields.char('Paypal Email Address'),
        'country':
        fields.char('Country', size=2),
        'location':
        fields.char('Location'),
        'shipping_service':
        fields.selection(_get_shipping_service_type, 'Shipping service'),
        'after_service_7_template':
        fields.text('7 days template'),
        'after_service_15_template':
        fields.text('15 days template'),
        'after_service_25_template':
        fields.text('25 days template'),
        # User Preferences
        'exclude_ship_to_location':
        fields.text('Exclude Ship To Location', readonly=True),
    }

    _defaults = {
        'feedback_score':
        0,
        'store_owner':
        0,
        'ownership':
        0,
        'sandbox':
        0,
        'sale_site':
        '0',
        'country':
        'CN',
        'location':
        'ShenZhen',
        'shipping_service':
        'sgam',
        'after_service_7_template':
        '''
Hi friend.
  Your item has been shipped on {{ shipped_time }} by air mail,
  and it may take about 10~20 days to arrive,
  sometimes it may be delayed by unexpected reason like holiday,
  custom`s process, weather condition etc.
  It may be delayed up to 35 days to arrive.
  We will be very appreciated for your patience.
  If you have any question, feel free to contact us asap.
  Thanks for your purchase.
  
  Yours Sincerely
''',
        'after_service_15_template':
        '''
Hi friend.
  Your item has been shipped on {{ shipped_time }} by air mail.
  {{ elapse }} days have passed since your item was shipped,
  When you receive it, we sincerely hope that you will like it 
  and appreciate our customer services.
  If there is anything you feel unsatisfied with, please do tell us. 
  This will help us know what we should do to help you as well as how we should improve.
  If you are satisfied, we sincerely hope that you can leave us a positive comment, 
  which is of vital importance to the growth of our small company.
  PLEASE DO NOT leaves us negative feedback. If you are not satisfied in any regard,
  please tell us.
  Thanks once more for your purchase.
  
  Yours Sincerely
''',
        'after_service_25_template':
        '''
Hi friend.
  Your item has been shipped on {{ shipped_time }} by air mail.
  If you haven't received your item and this situation lasts to the 35th day,
  please do contact us. WE WILL DO OUR BEST TO SOLVE YOUR PROBLEM.
  We do not want to give you a bad buying experience even when the shipping is out of our control.
  But if you receive it, we sincerely hope you can leave us a positive comment if you like it and
  appreciate our customer services.
  Thanks once more for your purchase.

  Yours Sincerely
'''
    }

    _order = 'monthly_sales desc'

    _sql_constraints = [
        ('name_uniq', 'unique(name, sandbox)', 'User ID must be unique!'),
    ]

    def copy(self, cr, uid, id, default=None, context=None):
        if default is None:
            default = {}

        name = self.read(cr, uid, id, ['name'], context=context)['name']
        default = default.copy()
        default.update({
            'name': name + _(' (Copy)'),
            'session_id': '',
            'ebay_auth_token': '',
        })

        return super(ebay_user, self).copy(cr, uid, id, default, context)

    def action_get_user(self, cr, uid, ids, context=None):
        for user in self.browse(cr, uid, ids, context=context):
            call_data = dict()
            call_data['UserID'] = user.name
            error_msg = 'Get the data for the specified user %s' % user.name
            reply = self.pool.get('ebay.ebay').call(
                cr,
                uid,
                user,
                'GetUser',
                call_data,
                error_msg,
                context=context).response.reply
            vals = dict()
            user_dict = reply.User
            vals['email'] = user_dict.Email
            vals['feedback_rating_star'] = user_dict.FeedbackRatingStar
            vals['feedback_score'] = user_dict.FeedbackScore
            vals[
                'positive_feedback_percent'] = user_dict.PositiveFeedbackPercent
            vals['registration_date'] = user_dict.RegistrationDate
            seller_info = user_dict.SellerInfo
            vals['store_owner'] = seller_info.StoreOwner == "true"
            if vals['store_owner']:
                vals['store_site'] = seller_info.StoreSite
                vals['store_url'] = seller_info.StoreURL
            vals['top_rated_seller'] = seller_info.get('TopRatedSeller', False)
            vals['site'] = user_dict.Site
            vals[
                'unique_negative_feedback_count'] = user_dict.UniqueNegativeFeedbackCount
            vals[
                'unique_neutral_feedback_count'] = user_dict.UniqueNeutralFeedbackCount
            vals[
                'unique_positive_feedback_count'] = user_dict.UniquePositiveFeedbackCount

            call_data = dict()
            call_data['ShowSellerExcludeShipToLocationPreference'] = 'true'
            error_msg = 'Get the user perferences for the user %s' % user.name
            reply = self.pool.get('ebay.ebay').call(
                cr,
                uid,
                user,
                'GetUserPreferences',
                call_data,
                error_msg,
                context=context).response.reply
            exclude_ship_to_location = reply.SellerExcludeShipToLocationPreferences.ExcludeShipToLocation
            if type(exclude_ship_to_location) != list:
                vals['exclude_ship_to_location'] = exclude_ship_to_location
            else:
                vals['exclude_ship_to_location'] = '|'.join(
                    exclude_ship_to_location)

            user.write(vals)

    def action_get_seller_list(self, cr, uid, ids, context=None):
        ebay_seller_list_obj = self.pool.get('ebay.seller.list')

        try:
            for user in self.browse(cr, uid, ids, context=context):
                ebay_seller_list_obj.get_seller_list(cr,
                                                     uid,
                                                     user,
                                                     context=context)
        except (ConnectionError, ConnectionResponseError,
                RequestException) as e:
            return self.pool.get('ebay.ebay').exception(cr,
                                                        uid,
                                                        'GetSellerList',
                                                        e,
                                                        context=context)
        else:
            return True
Exemplo n.º 15
0
     ], 'Package Type', help='Indicates the type of package'),
 'bill_shipping': fields.selection([
     ('shipper', 'Shipper'),
     ('receiver', 'Receiver'),
     ('thirdparty', 'Third Party')
     ], 'Bill Shipping to', help='Shipper, Receiver, or Third Party.'),
 'with_ret_service': fields.boolean('With Return Services', help='Include Return Shipping Information in the package.'),
 'tot_ship_weight': fields.function(_total_weight_net, method=True, type='float', digits=(16, 3), string='Total Shipment Weight',
     store={
         'stock.picking': (lambda self, cr, uid, ids, c={}: ids, ['packages_ids'], -10),
         'stock.packages': (_get_order, ['weight'], -10),
         }, help="Adds the Total Weight of all the packages in the Packages Table.",
         ),
 'tot_del_order_weight': fields.function(_total_ord_weight_net, method=True, readonly=True, string='Total Order Weight', store=False,
                                          help="Adds the Total Weight of all the packages in the Packages Table."),
 'packages_ids': fields.one2many("stock.packages", 'pick_id', 'Packages Table'),
 'ship_state': fields.selection([
     ('draft', 'Draft'),
     ('in_process', 'In Process'),
     ('ready_pick', 'Ready for Pickup'),
     ('shipped', 'Shipped'),
     ('delivered', 'Delivered'),
     ('void', 'Void'),
     ('hold', 'Hold'),
     ('cancelled', 'Cancelled')
     ], 'Shipping Status', readonly=True, help='The current status of the shipment'),
 'trade_mark': fields.text('Trademarks AREA'),
 'ship_message': fields.text('Message'),
 'address_validate': fields.selection([
     ('validate', 'Validate'),
     ('nonvalidate', 'No Validation')
Exemplo n.º 16
0
    _columns = {
        'name': fields.char('Name', size=64, help="Exchange description like the name of the supplier, bank,...", require=True),
        'type': fields.selection([('in','IN'),('out','OUT'),('in-out', 'IN & OUT')], 'Type',help=("IN for files coming from the other system"
                                                                "and to be imported in the ERP ; OUT for files to be"
                                                                "generated from the ERP and send to the other system")),
        'mapping_id':fields.many2one('external.mapping', 'External Mapping', require="True", domain="[('referential_id', '=', referential_id)]"),
        'format' : fields.selection([('csv','CSV'),('csv_no_header','CSV WITHOUT HEADER'), ('xls', 'XLS')], 'File format'),
        'referential_id':fields.many2one('external.referential', 'Referential',help="Referential to use for connection and mapping", require=True),
        'scheduler':fields.many2one('ir.cron', 'Scheduler',help="Scheduler that will execute the cron task"),
        'search_filter':  fields.char('Search Filter', size=256),
        'filename': fields.char('Filename', size=128, help="Filename will be used to generate the output file name or to read the incoming file. It is possible to use variables (check in sequence for syntax)", require=True),
        'folder_path': fields.char('Folder Path', size=128, help="folder that containt the incomming or the outgoing file"),
        'archive_folder_path': fields.char('Archive Folder Path', size=128, help="if a path is set when a file is imported the file will be automatically moved to this folder"),
        'encoding': fields.selection(_get_encoding, 'Encoding', require=True),
        'field_ids': fields.one2many('file.fields', 'file_id', 'Fields'),
        'action_before_all': fields.text('Action Before All', help="This python code will executed after the import/export"),
        'action_after_all': fields.text('Action After All', help="This python code will executed after the import/export"),
        'action_before_each': fields.text('Action Before Each', help="This python code will executed after each element of the import/export"),
        'action_after_each': fields.text('Action After Each', help="This python code will executed after each element of the import/export"),
        'check_if_import': fields.text('Check If Import', help="This python code will be executed before each element of the import"),
        'delimiter':fields.char('Fields delimiter', size=64, help="Delimiter used in the CSV file"),
        'lang': fields.many2one('res.lang', 'Language'),
        'import_default_fields':fields.one2many('file.default.import.values', 'file_id', 'Default Field'),
        'do_not_update':fields.boolean('Do Not Update'),
        'pre_processing': fields.text('Pre-Processing', help="This python code will be executed before merge of elements of the import"),
        'mapping_template_id':fields.many2one('external.mapping.template', 'External Mapping Template', require="True"),
        'notes': fields.text('Notes'),
        'related_mapping_ids': fields.function(_get_related_mapping_ids, type="many2many", relation="external.mapping", string='Related Mappings'),
        'synchronize_from': fields.selection([('referential', 'Referential'), ('pop_up', 'Pop Up')], string='Synchronize From'),
        'linked_task': fields.many2one('file.exchange', 'Linked Task'),
Exemplo n.º 17
0
class mrp_servicemc(osv.osv):
    _name = 'mrp.servicemc'
    _inherit = 'mail.thread'
    _description = 'servicemc Order'

    def _amount_untaxed(self, cr, uid, ids, field_name, arg, context=None):
        """ Calculates untaxed amount.
        @param self: The object pointer
        @param cr: The current row, from the database cursor,
        @param uid: The current user ID for security checks
        @param ids: List of selected IDs
        @param field_name: Name of field.
        @param arg: Argument
        @param context: A standard dictionary for contextual values
        @return: Dictionary of values.
        """
        res = {}
        cur_obj = self.pool.get('res.currency')

        for servicemc in self.browse(cr, uid, ids, context=context):
            res[servicemc.id] = 0.0
            for line in servicemc.operations:
                res[servicemc.id] += line.price_subtotal
            for line in servicemc.fees_lines:
                res[servicemc.id] += line.price_subtotal
            cur = servicemc.pricelist_id.currency_id
            res[servicemc.id] = cur_obj.round(cr, uid, cur, res[servicemc.id])
        return res

    def _amount_tax(self, cr, uid, ids, field_name, arg, context=None):
        """ Calculates taxed amount.
        @param field_name: Name of field.
        @param arg: Argument
        @return: Dictionary of values.
        """
        res = {}
        #return {}.fromkeys(ids, 0)
        cur_obj = self.pool.get('res.currency')
        tax_obj = self.pool.get('account.tax')
        for servicemc in self.browse(cr, uid, ids, context=context):
            val = 0.0
            cur = servicemc.pricelist_id.currency_id
            for line in servicemc.operations:
                #manage prices with tax included use compute_all instead of compute
                if line.to_invoice:
                    tax_calculate = tax_obj.compute_all(cr, uid, line.tax_id, line.price_unit, line.product_uom_qty, line.product_id, servicemc.partner_id)
                    for c in tax_calculate['taxes']:
                        val += c['amount']
            for line in servicemc.fees_lines:
                if line.to_invoice:
                    tax_calculate = tax_obj.compute_all(cr, uid, line.tax_id, line.price_unit, line.product_uom_qty,  line.product_id, servicemc.partner_id)
                    for c in tax_calculate['taxes']:
                        val += c['amount']
            res[servicemc.id] = cur_obj.round(cr, uid, cur, val)
        return res

    def _amount_total(self, cr, uid, ids, field_name, arg, context=None):
        """ Calculates total amount.
        @param field_name: Name of field.
        @param arg: Argument
        @return: Dictionary of values.
        """
        res = {}
        untax = self._amount_untaxed(cr, uid, ids, field_name, arg, context=context)
        tax = self._amount_tax(cr, uid, ids, field_name, arg, context=context)
        cur_obj = self.pool.get('res.currency')
        for id in ids:
            servicemc = self.browse(cr, uid, id, context=context)
            cur = servicemc.pricelist_id.currency_id
            res[id] = cur_obj.round(cr, uid, cur, untax.get(id, 0.0) + tax.get(id, 0.0))
        return res

    def _get_default_address(self, cr, uid, ids, field_name, arg, context=None):
        res = {}
        partner_obj = self.pool.get('res.partner')
        for data in self.browse(cr, uid, ids, context=context):
            adr_id = False
            if data.partner_id:
                adr_id = partner_obj.address_get(cr, uid, [data.partner_id.id], ['default'])['default']
            res[data.id] = adr_id
        return res

    def _get_lines(self, cr, uid, ids, context=None):
        return self.pool['mrp.servicemc'].search(
            cr, uid, [('operations', 'in', ids)], context=context)

    def _get_fee_lines(self, cr, uid, ids, context=None):
        return self.pool['mrp.servicemc'].search(
            cr, uid, [('fees_lines', 'in', ids)], context=context)

    _columns = {
        'facproducto': fields.many2one('product.product','Producto'),   
        'facpreciounitario': fields.float('Precio unitario', help = 'Precio unitario',  required=True), 
        'facimpuestos': fields.many2many('account.tax', 'repair_operation_line_tax', 'repair_operation_line_id', 'tax_id', 'Impuesto'),
        'facafacturar':fields.boolean('A facturar'),
        'facsubtotal':fields.float('Subtotal'),
        'total': fields.float('Total'),
        'faccantidad': fields.float('Cantidad',help = 'Cantidad',required=True),
        'noeconomicomc':fields.char('Numero Economico',size=24),
        'noseriemc':fields.char('Numero de Serie',size=24),
        'name': fields.char('servicemc Reference',size=24, required=True, states={'confirmed':[('readonly',True)]}),
        'product_id': fields.many2one('product.product', string='Product to give service', required=True, readonly=True, states={'draft':[('readonly',False)]}),
        'partner_id' : fields.many2one('res.partner', 'Partner', select=True, help='Choose partner for whom the order will be invoiced and delivered.', states={'confirmed':[('readonly',True)]}),
        'address_id': fields.many2one('res.partner', 'Delivery Address', domain="[('parent_id','=',partner_id)]", states={'confirmed':[('readonly',True)]}),
        'default_address_id': fields.function(_get_default_address, type="many2one", relation="res.partner"),
        'prodlot_id': fields.many2one('stock.production.lot', 'Lot Number', select=True, states={'draft':[('readonly',False)]},domain="[('product_id','=',product_id)]"),
        'state': fields.selection([
            ('draft','Quotation'),
            ('cancel','Cancelled'),
            ('confirmed','Confirmed'),
            ('under_servicemc','Under servicio'),
            ('ready','listo para dar servicio'),
            ('2binvoiced','To be Invoiced'),
            ('invoice_except','Invoice Exception'),
            ('done','Hecho')
            ], 'Status', readonly=True, track_visibility='onchange',
            help=' * The \'Draft\' status is used when a user is encoding a new and unconfirmed servicemc order. \
            \n* The \'Confirmed\' status is used when a user confirms the servicemc order. \
            \n* The \'Ready to servicemc\' status is used to start to servicemcing, user can start servicemcing only after servicemc order is confirmed. \
            \n* The \'To be Invoiced\' status is used to generate the invoice before or after servicemcing done. \
            \n* The \'Done\' status is set when servicemcing is completed.\
            \n* The \'Cancelled\' status is used when user cancel servicemc order.'),
        'location_id': fields.many2one('stock.location', 'Current Location', select=True, readonly=True, states={'draft':[('readonly',False)], 'confirmed':[('readonly',True)]}),
        'location_dest_id': fields.many2one('stock.location', 'Delivery Location', readonly=True, states={'draft':[('readonly',False)], 'confirmed':[('readonly',True)]}),
        'move_id': fields.many2one('stock.move', 'Move',required=True, domain="[('product_id','=',product_id)]", readonly=True, states={'draft':[('readonly',False)]}),
        'guarantee_limit': fields.date('Warranty Expiration', help="The warranty expiration limit is computed as: last move date + warranty defined on selected product. If the current date is below the warranty expiration limit, each operation and fee you will add will be set as 'not to invoiced' by default. Note that you can change manually afterwards.", states={'confirmed':[('readonly',True)]}),
        'operations' : fields.one2many('mrp.servicemc.line', 'servicemc_id', 'Operation Lines', readonly=True, states={'draft':[('readonly',False)]}),
        'pricelist_id': fields.many2one('product.pricelist', 'Pricelist', help='Pricelist of the selected partner.'),
        'partner_invoice_id':fields.many2one('res.partner', 'Invoicing Address'),
        'invoice_method':fields.selection([
            ("none","No Invoice"),
            ("b4servicemc","Before servicemc"),
            ("after_servicemc","After servicemc")
           ], "Invoice Method",
            select=True, required=True, states={'draft':[('readonly',False)]}, readonly=True, help='Selecting \'Before servicemc\' or \'After servicemc\' will allow you to generate invoice before or after the servicemc is done respectively. \'No invoice\' means you don\'t want to generate invoice for this servicemc order.'),
        'invoice_id': fields.many2one('account.invoice', 'Invoice', readonly=True),
        'picking_id': fields.many2one('stock.picking', 'Picking',readonly=True),
        'fees_lines': fields.one2many('mrp.servicemc.fee', 'servicemc_id', 'Fees Lines', readonly=True, states={'draft':[('readonly',False)]}),
        'internal_notes': fields.text('Internal Notes'),
        'quotation_notes': fields.text('Quotation Notes'),
        'company_id': fields.many2one('res.company', 'Company'),
        'deliver_bool': fields.boolean('Deliver', help="Check this box if you want to manage the delivery once the product is servicemced and create a picking with selected product. Note that you can select the locations in the Info tab, if you have the extended view.", states={'confirmed':[('readonly',True)]}),
        'invoiced': fields.boolean('Invoiced', readonly=True),
        'servicemced': fields.boolean('Entregado', readonly=True),
        'amount_untaxed': fields.function(_amount_untaxed, string='Untaxed Amount',
            store={
                'mrp.servicemc': (lambda self, cr, uid, ids, c={}: ids, ['operations', 'fees_lines'], 10),
                'mrp.servicemc.line': (_get_lines, ['price_unit', 'price_subtotal', 'product_id', 'tax_id', 'product_uom_qty', 'product_uom'], 10),
                'mrp.servicemc.fee': (_get_fee_lines, ['price_unit', 'price_subtotal', 'product_id', 'tax_id', 'product_uom_qty', 'product_uom'], 10),
            }),
        'amount_tax': fields.function(_amount_tax, string='Taxes',
            store={
                'mrp.servicemc': (lambda self, cr, uid, ids, c={}: ids, ['operations', 'fees_lines'], 10),
                'mrp.servicemc.line': (_get_lines, ['price_unit', 'price_subtotal', 'product_id', 'tax_id', 'product_uom_qty', 'product_uom'], 10),
                'mrp.servicemc.fee': (_get_fee_lines, ['price_unit', 'price_subtotal', 'product_id', 'tax_id', 'product_uom_qty', 'product_uom'], 10),
            }),
        'amount_total': fields.function(_amount_total, string='Total',
            store={
                'mrp.servicemc': (lambda self, cr, uid, ids, c={}: ids, ['operations', 'fees_lines'], 10),
                'mrp.servicemc.line': (_get_lines, ['price_unit', 'price_subtotal', 'product_id', 'tax_id', 'product_uom_qty', 'product_uom'], 10),
                'mrp.servicemc.fee': (_get_fee_lines, ['price_unit', 'price_subtotal', 'product_id', 'tax_id', 'product_uom_qty', 'product_uom'], 10),
            }),
         'clienteNombre': fields.many2one('res.partner','Nombre del Cliente', required= True),   
        'clienteEntregaNombre': fields.many2one('res.partner','Nombre del Cliente'),    
        'empresaEntregaNombre': fields.many2one('hr.employee','Nombre'),    
        'empresaNombre': fields.many2one('hr.employee','Nombre Jefe de Area'),      
        'produccion_fecha_final':  fields.date('Fecha final', required = False),
        'produccion_notas': fields.text('Notas'),
        'produccion_re_ter_unidad': fields.many2one('hr.employee','Reporta Terminio de la Unidad', required=False), 
        'calidad_fecha_inicial':  fields.date('Fecha Inicial', required = False),
        'calidad_fecha_final':  fields.date('Fecha Final', required = False),
        'calidad_notas': fields.text('Notas'),
        'calidad_re_li_unidad': fields.many2one('hr.employee','Reporta Terminio de la Unidad', required=False), 
        'calidad_fecha_liberacion':  fields.date('Fecha de Liberacion', required = False),
        'calidad_pri_inpeccion': fields.boolean('Primera Inspeccion'),
        'calidad_liberada': fields.boolean('Liberada'),
        'fecha_alta': fields.date('Fecha de Alta', required = True),
        'modelo_id': fields.many2one('fleet.vehicle','Modelo',required = True),
    }

    _defaults = {
        'state': lambda *a: 'draft',
        'deliver_bool': lambda *a: True,
        'name': lambda obj, cr, uid, context: obj.pool.get('ir.sequence').get(cr, uid, 'mrp.servicemc'),
        'invoice_method': lambda *a: 'none',
        'company_id': lambda self, cr, uid, context: self.pool.get('res.company')._company_default_get(cr, uid, 'mrp.servicemc', context=context),
        'pricelist_id': lambda self, cr, uid,context : self.pool.get('product.pricelist').search(cr, uid, [('type','=','sale')])[0]
    }

    def copy(self, cr, uid, id, default=None, context=None):
        if not default:
            default = {}
        default.update({
            'state':'draft',
            'servicemced':False,
            'invoiced':False,
            'invoice_id': False,
            'picking_id': False,
            'name': self.pool.get('ir.sequence').get(cr, uid, 'mrp.servicemc'),
        })
        return super(mrp_servicemc, self).copy(cr, uid, id, default, context)

    def onchange_product_id(self, cr, uid, ids, product_id=None):
        """ On change of product sets some values.
        @param product_id: Changed product
        @return: Dictionary of values.
        """
        return {'value': {
                    'prodlot_id': False,
                    'move_id': False,
                    'guarantee_limit' :False,
                    'location_id':  False,
                    'location_dest_id': False,
                }
        }

    def onchange_move_id(self, cr, uid, ids, prod_id=False, move_id=False):
        """ On change of move id sets values of guarantee limit, source location,
        destination location, partner and partner address.
        @param prod_id: Id of product in current record.
        @param move_id: Changed move.
        @return: Dictionary of values.
        """
        data = {}
        data['value'] = {'guarantee_limit': False, 'location_id': False, 'prodlot_id': False, 'partner_id': False}
        if not prod_id:
            return data
        if move_id:
            move =  self.pool.get('stock.move').browse(cr, uid, move_id)
            product = self.pool.get('product.product').browse(cr, uid, prod_id)
            limit = datetime.strptime(move.date_expected, '%Y-%m-%d %H:%M:%S') + relativedelta(months=int(product.warranty))
            data['value']['guarantee_limit'] = limit.strftime('%Y-%m-%d')
            data['value']['location_id'] = move.location_dest_id.id
            data['value']['location_dest_id'] = move.location_dest_id.id
            data['value']['prodlot_id'] = move.prodlot_id.id
            if move.partner_id:
                data['value']['partner_id'] = move.partner_id.id
            else:
                data['value']['partner_id'] = False
            d = self.onchange_partner_id(cr, uid, ids, data['value']['partner_id'], data['value']['partner_id'])
            data['value'].update(d['value'])
        return data

    def button_dummy(self, cr, uid, ids, context=None):
        return True

    def onchange_partner_id(self, cr, uid, ids, part, address_id):
        """ On change of partner sets the values of partner address,
        partner invoice address and pricelist.
        @param part: Changed id of partner.
        @param address_id: Address id from current record.
        @return: Dictionary of values.
        """
        part_obj = self.pool.get('res.partner')
        pricelist_obj = self.pool.get('product.pricelist')
        if not part:
            return {'value': {
                        'address_id': False,
                        'partner_invoice_id': False,
                        'pricelist_id': pricelist_obj.search(cr, uid, [('type','=','sale')])[0]
                    }
            }
        addr = part_obj.address_get(cr, uid, [part], ['delivery', 'invoice', 'default'])
        partner = part_obj.browse(cr, uid, part)
        pricelist = partner.property_product_pricelist and partner.property_product_pricelist.id or False
        return {'value': {
                    'address_id': addr['delivery'] or addr['default'],
                    'partner_invoice_id': addr['invoice'],
                    'pricelist_id': pricelist
                }
        }

    def onchange_lot_id(self, cr, uid, ids, lot, product_id):
        """ On change of Serial Number sets the values of source location,
        destination location, move and guarantee limit.
        @param lot: Changed id of Serial Number.
        @param product_id: Product id from current record.
        @return: Dictionary of values.
        """
        move_obj = self.pool.get('stock.move')
        data = {}
        data['value'] = {
            'location_id': False,
            'location_dest_id': False,
            'move_id': False,
            'guarantee_limit': False
        }

        if not lot:
            return data
        move_ids = move_obj.search(cr, uid, [('prodlot_id', '=', lot)])

        if not len(move_ids):
            return data

        def get_last_move(lst_move):
            while lst_move.move_dest_id and lst_move.move_dest_id.state == 'done':
                lst_move = lst_move.move_dest_id
            return lst_move

        move_id = move_ids[0]
        move = get_last_move(move_obj.browse(cr, uid, move_id))
        data['value']['move_id'] = move.id
        d = self.onchange_move_id(cr, uid, ids, product_id, move.id)
        data['value'].update(d['value'])
        return data

    def action_cancel_draft(self, cr, uid, ids, *args):
        """ Cancels servicemc order when it is in 'Draft' state.
        @param *arg: Arguments
        @return: True
        """
        if not len(ids):
            return False
        mrp_line_obj = self.pool.get('mrp.servicemc.line')
        for servicemc in self.browse(cr, uid, ids):
            mrp_line_obj.write(cr, uid, [l.id for l in servicemc.operations], {'state': 'draft'})
        self.write(cr, uid, ids, {'state':'draft'})
        wf_service = netsvc.LocalService("workflow")
        for id in ids:
            wf_service.trg_create(uid, 'mrp.servicemc', id, cr)
        return True

    def action_confirm(self, cr, uid, ids, *args):
        """ servicemc order state is set to 'To be invoiced' when invoice method
        is 'Before servicemc' else state becomes 'Confirmed'.
        @param *arg: Arguments
        @return: True
        """
        mrp_line_obj = self.pool.get('mrp.servicemc.line')
        for o in self.browse(cr, uid, ids):
            if (o.invoice_method == 'b4servicemc'):
                self.write(cr, uid, [o.id], {'state': '2binvoiced'})
            else:
                self.write(cr, uid, [o.id], {'state': 'confirmed'})
                for line in o.operations:
                    if line.product_id.track_production and not line.prodlot_id:
                        raise osv.except_osv(_('Warning!'), _("Serial number is required for operation line with product '%s'") % (line.product_id.name))
                mrp_line_obj.write(cr, uid, [l.id for l in o.operations], {'state': 'confirmed'})
        return True

    def action_cancel(self, cr, uid, ids, context=None):
        """ Cancels servicemc order.
        @return: True
        """
        mrp_line_obj = self.pool.get('mrp.servicemc.line')
        for servicemc in self.browse(cr, uid, ids, context=context):
            if not servicemc.invoiced:
                mrp_line_obj.write(cr, uid, [l.id for l in servicemc.operations], {'state': 'cancel'}, context=context)
            else:
                raise osv.except_osv(_('Warning!'),_('servicemc order is already invoiced.'))
        return self.write(cr,uid,ids,{'state':'cancel'})

    def wkf_invoice_create(self, cr, uid, ids, *args):
        self.action_invoice_create(cr, uid, ids)
        return True

    def action_invoice_create(self, cr, uid, ids, group=False, context=None):
        """ Creates invoice(s) for servicemc order.
        @param group: It is set to true when group invoice is to be generated.
        @return: Invoice Ids.
        """
        res = {}
        invoices_group = {}
        inv_line_obj = self.pool.get('account.invoice.line')
        inv_obj = self.pool.get('account.invoice')
        servicemc_line_obj = self.pool.get('mrp.servicemc.line')
        servicemc_fee_obj = self.pool.get('mrp.servicemc.fee')
        for servicemc in self.browse(cr, uid, ids, context=context):
            res[servicemc.id] = False
            if servicemc.state in ('draft','cancel') or servicemc.invoice_id:
                continue
            if not (servicemc.partner_id.id and servicemc.partner_invoice_id.id):
                raise osv.except_osv(_('No partner!'),_('You have to select a Partner Invoice Address in the servicemc form!'))
            comment = servicemc.quotation_notes
            if (servicemc.invoice_method != 'none'):
                if group and servicemc.partner_invoice_id.id in invoices_group:
                    inv_id = invoices_group[servicemc.partner_invoice_id.id]
                    invoice = inv_obj.browse(cr, uid, inv_id)
                    invoice_vals = {
                        'name': invoice.name +', '+servicemc.name,
                        'origin': invoice.origin+', '+servicemc.name,
                        'comment':(comment and (invoice.comment and invoice.comment+"\n"+comment or comment)) or (invoice.comment and invoice.comment or ''),
                    }
                    inv_obj.write(cr, uid, [inv_id], invoice_vals, context=context)
                else:
                    if not servicemc.partner_id.property_account_receivable:
                        raise osv.except_osv(_('Error!'), _('No account defined for partner "%s".') % servicemc.partner_id.name )
                    account_id = servicemc.partner_id.property_account_receivable.id
                    inv = {
                        'name': servicemc.name,
                        'origin':servicemc.name,
                        'type': 'out_invoice',
                        'account_id': account_id,
                        'partner_id': servicemc.partner_id.id,
                        'currency_id': servicemc.pricelist_id.currency_id.id,
                        'comment': servicemc.quotation_notes,
                        'fiscal_position': servicemc.partner_id.property_account_position.id
                    }
                    inv_id = inv_obj.create(cr, uid, inv)
                    invoices_group[servicemc.partner_invoice_id.id] = inv_id
                self.write(cr, uid, servicemc.id, {'invoiced': True, 'invoice_id': inv_id})

                for operation in servicemc.operations:
                    if operation.to_invoice == True:
                        if group:
                            name = servicemc.name + '-' + operation.name
                        else:
                            name = operation.name

                        if operation.product_id.property_account_income:
                            account_id = operation.product_id.property_account_income.id
                        elif operation.product_id.categ_id.property_account_income_categ:
                            account_id = operation.product_id.categ_id.property_account_income_categ.id
                        else:
                            raise osv.except_osv(_('Error!'), _('No account defined for product "%s".') % operation.product_id.name )

                        invoice_line_id = inv_line_obj.create(cr, uid, {
                            'invoice_id': inv_id,
                            'name': name,
                            'origin': servicemc.name,
                            'account_id': account_id,
                            'quantity': operation.product_uom_qty,
                            'invoice_line_tax_id': [(6,0,[x.id for x in operation.tax_id])],
                            'uos_id': operation.product_uom.id,
                            'price_unit': operation.price_unit,
                            'price_subtotal': operation.product_uom_qty*operation.price_unit,
                            'product_id': operation.product_id and operation.product_id.id or False
                        })
                        servicemc_line_obj.write(cr, uid, [operation.id], {'invoiced': True, 'invoice_line_id': invoice_line_id})
                for fee in servicemc.fees_lines:
                    if fee.to_invoice == True:
                        if group:
                            name = servicemc.name + '-' + fee.name
                        else:
                            name = fee.name
                        if not fee.product_id:
                            raise osv.except_osv(_('Warning!'), _('No product defined on Fees!'))

                        if fee.product_id.property_account_income:
                            account_id = fee.product_id.property_account_income.id
                        elif fee.product_id.categ_id.property_account_income_categ:
                            account_id = fee.product_id.categ_id.property_account_income_categ.id
                        else:
                            raise osv.except_osv(_('Error!'), _('No account defined for product "%s".') % fee.product_id.name)

                        invoice_fee_id = inv_line_obj.create(cr, uid, {
                            'invoice_id': inv_id,
                            'name': name,
                            'origin': servicemc.name,
                            'account_id': account_id,
                            'quantity': fee.product_uom_qty,
                            'invoice_line_tax_id': [(6,0,[x.id for x in fee.tax_id])],
                            'uos_id': fee.product_uom.id,
                            'product_id': fee.product_id and fee.product_id.id or False,
                            'price_unit': fee.price_unit,
                            'price_subtotal': fee.product_uom_qty*fee.price_unit
                        })
                        servicemc_fee_obj.write(cr, uid, [fee.id], {'invoiced': True, 'invoice_line_id': invoice_fee_id})
                res[servicemc.id] = inv_id
        return res

    def action_servicemc_ready(self, cr, uid, ids, context=None):
        """ Writes servicemc order state to 'Ready'
        @return: True
        """
        for servicemc in self.browse(cr, uid, ids, context=context):
            self.pool.get('mrp.servicemc.line').write(cr, uid, [l.id for
                    l in servicemc.operations], {'state': 'confirmed'}, context=context)
            self.write(cr, uid, [servicemc.id], {'state': 'ready'})
        return True

    def action_servicemc_start(self, cr, uid, ids, context=None):
        """ Writes servicemc order state to 'Under servicemc'
        @return: True
        """
        servicemc_line = self.pool.get('mrp.servicemc.line')
        for servicemc in self.browse(cr, uid, ids, context=context):
            servicemc_line.write(cr, uid, [l.id for
                    l in servicemc.operations], {'state': 'confirmed'}, context=context)
            servicemc.write({'state': 'under_servicemc'})
        return True

    def action_servicemc_end(self, cr, uid, ids, context=None):
        """ Writes servicemc order state to 'To be invoiced' if invoice method is
        After servicemc else state is set to 'Ready'.
        @return: True
        """
        for order in self.browse(cr, uid, ids, context=context):
            val = {}
            val['servicemced'] = True
            if (not order.invoiced and order.invoice_method=='after_servicemc'):
                val['state'] = '2binvoiced'
            elif (not order.invoiced and order.invoice_method=='b4servicemc'):
                val['state'] = 'ready'
            else:
                pass
            self.write(cr, uid, [order.id], val)
        return True

    def wkf_servicemc_done(self, cr, uid, ids, *args):
        self.action_servicemc_done(cr, uid, ids)
        return True

    def action_servicemc_done(self, cr, uid, ids, context=None):
        """ Creates stock move and picking for servicemc order.
        @return: Picking ids.
        """
        res = {}
        move_obj = self.pool.get('stock.move')
        wf_service = netsvc.LocalService("workflow")
        servicemc_line_obj = self.pool.get('mrp.servicemc.line')
        seq_obj = self.pool.get('ir.sequence')
        pick_obj = self.pool.get('stock.picking')
        for servicemc in self.browse(cr, uid, ids, context=context):
            for move in servicemc.operations:
                move_id = move_obj.create(cr, uid, {
                    'name': move.name,
                    'product_id': move.product_id.id,
                    'product_qty': move.product_uom_qty,
                    'product_uom': move.product_uom.id,
                    'partner_id': servicemc.address_id and servicemc.address_id.id or False,
                    'location_id': move.location_id.id,
                    'location_dest_id': move.location_dest_id.id,
                    'tracking_id': False,
                    'prodlot_id': move.prodlot_id and move.prodlot_id.id or False,
                    'state': 'assigned',
                })
                move_obj.action_done(cr, uid, [move_id], context=context)
                servicemc_line_obj.write(cr, uid, [move.id], {'move_id': move_id, 'state': 'done'}, context=context)
            if servicemc.deliver_bool:
                pick_name = seq_obj.get(cr, uid, 'stock.picking.out')
                picking = pick_obj.create(cr, uid, {
                    'name': pick_name,
                    'origin': servicemc.name,
                    'state': 'draft',
                    'move_type': 'one',
                    'partner_id': servicemc.address_id and servicemc.address_id.id or False,
                    'note': servicemc.internal_notes,
                    'invoice_state': 'none',
                    'type': 'out',
                })
                move_id = move_obj.create(cr, uid, {
                    'name': servicemc.name,
                    'picking_id': picking,
                    'product_id': servicemc.product_id.id,
                    'product_uom': servicemc.product_id.uom_id.id,
                    'prodlot_id': servicemc.prodlot_id and servicemc.prodlot_id.id or False,
                    'partner_id': servicemc.address_id and servicemc.address_id.id or False,
                    'location_id': servicemc.location_id.id,
                    'location_dest_id': servicemc.location_dest_id.id,
                    'tracking_id': False,
                    'state': 'assigned',
                })
                wf_service.trg_validate(uid, 'stock.picking', picking, 'button_confirm', cr)
                self.write(cr, uid, [servicemc.id], {'state': 'done', 'picking_id': picking})
                res[servicemc.id] = picking
            else:
                self.write(cr, uid, [servicemc.id], {'state': 'done'})
        return res
Exemplo n.º 18
0
class res_users(osv.osv):
    _inherit = 'res.users'
    _columns = {
        'quarantine_files_ids': fields.one2many('antivir.quarantine', 'user_id', 'Quarantine files')
    }
Exemplo n.º 19
0
class hr_contract_mod_wiz(osv.TransientModel):
    _name = 'hr.contract.mod.wiz'
    _description = 'Mis a jour salaire en masse'
    _columns = {
        'date': fields.date('Date', required=True),
        'perc_increase': fields.float('Pourcentage augmentation', required=True),
        'amount_increase': fields.float('Montant augmentation', required=True),
        'start': fields.many2one('account.period', 'Date effet'),  # Rétro-actif depuis               
        'period_id': fields.many2one('account.period', 'Periode applicable', required=True, domain=[('date_start', '>', datetime.date.today().strftime('%Y-01-01'))]),
        'employee_ids': fields.many2many('hr.employee', 'cont_dept_emp_rel', 'sum_id', 'emp_id', 'Employee(s)', domain=[('active', '=', True)]),
        'rubrique_ids':fields.one2many('rubrique.line.wiz', 'cont_mod_id', 'Rubriques'),
        }

    def generate(self, cr, uid, ids, context=None):
        data = self.read(cr, uid, ids, [])[0]
        # raise osv.except_osv(_('data'),_('data = %s')%(data))
        contract_obj = self.pool.get('hr.contract')
        period_obj = self.pool.get('account.period')
        proposal_obj = self.pool.get('hr.salary.proposal')
        proposal_line_obj = self.pool.get('hr.salary.proposal.line')
        period_id = period_obj.browse(cr, uid, [data['period_id'][0]])[0]
        start = period_obj.browse(cr, uid, [data['start'][0]])[0]
        prev_period_id = period_obj.browse(cr, uid, [data['period_id'][0] - 1])[0]
        rub_line_obj = self.pool.get('rub.update.line')
        ############################################################
        # if data:
        #    raise osv.except_osv(_('data'), _('%s')%data)
        v = data['period_id'][0]
        period_id = period_obj.browse(cr, uid, [v])[0]  # periode de paie et return an object type class
        start = period_obj.browse(cr, uid, [data['start'][0]])[0]  # periode pour les rappels
        # prev_period_id=period_obj.browse(cr,uid,[data['period_id'][0]-1])[0]
        
        created = []
        if not data['employee_ids']:
            raise osv.except_osv(_('Error'), _('You have to select at least 1 Employee. And try again'))
        proposal = proposal_obj.search(cr, uid, [('name', '=', period_id.id)])  # return list of result
        if proposal == []:
            proposal = proposal_obj.create(cr, uid,
                    {'name':period_id.id, 'start':start.id, 'date':datetime.date.today().strftime('%Y-%m-%d')})
        else:
            proposal = proposal[0]
        created.append(proposal)  # "id du proposition salariale (list) identifier par la période"
        date_today = datetime.date.today().strftime('%Y-%m-%d')
        contract_ids1 = contract_obj.search(cr, uid,
                    [('employee_id', 'in', data['employee_ids']),
                    '|', ('date_end', '=', False), ('date_end', '>=', date_today)])  # ou date_end est dans le futur(> today)
        contract_ids = contract_obj.read(cr, uid, contract_ids1, ['wage'])
        # raise osv.except_osv(_('contract_ids'),_('contract_ids = %s \n contract_ids1 = %s')%(contract_ids,contract_ids1))
        for contract in contract_ids:
            proposal_line = proposal_line_obj.search(cr, uid,
                    [('proposal_id', '=', created[0]), ('contract_id', '=', contract['id'])])
            if proposal_line == []:
                wage = contract['wage'] + (contract['wage'] * (data['perc_increase']) / 100) + data['amount_increase']
                pl = proposal_line_obj.create(cr, uid,
                        {'contract_id':contract['id'], 'salary_proposal':wage, 'proposal_id':created[0]})
                rubrique_lines = self.pool.get('rubrique.line.wiz').browse(cr, uid, data['rubrique_ids'])
                for rubrique in rubrique_lines:      
                    rub = {'proposal_line_id':pl,
                        'name':rubrique.name.id,
                        'perc_increase': rubrique.perc_increase,
                        'amount_increase': rubrique.amount_increase,
                        }
                    rub_line_obj.create(cr, uid, rub)
            else:
                wage = 0
                pl = 0
                if data['perc_increase'] != 0 or data['amount_increase'] != 0:
                    wage = contract['wage'] + (contract['wage'] * (data['perc_increase']) / 100) + data['amount_increase']
                    pl = proposal_line_obj.write(cr, uid, proposal_line[0],
                        {'contract_id':contract['id'], 'salary_proposal':wage, 'proposal_id':created[0]})
                else:
                    pl = proposal_line_obj.write(cr, uid, proposal_line[0],
                        {'contract_id':contract['id'], 'proposal_id':created[0]})
                # pl=proposal_line_obj.write(cr,uid,proposal_line[0],{'contract_id':contract['id'],'salary_proposal':wage,'proposal_id':created[0]})
                rubrique_lines = self.pool.get('rubrique.line.wiz').browse(cr, uid, data['rubrique_ids'])
                for rubrique in rubrique_lines:
                    condition = [('name', '=', rubrique.name.id), ('proposal_line_id', '=', proposal_line[0])]
                    search_id = rub_line_obj.search(cr, uid, condition)
                    rub = {'proposal_line_id':proposal_line[0],
                        'name':rubrique.name.id,
                        'perc_increase': rubrique.perc_increase,
                        'amount_increase': rubrique.amount_increase,
                        }
                    is_rub_exist = False
                    if len(search_id) == 0:
                        is_rub_exist = False
                    else:
                        is_rub_exist = True
                    if not is_rub_exist:
                        rub_line_obj.create(cr, uid, rub)
                    else:
                        rub_line_obj.write(cr, uid, search_id[0], rub)

        ##################################################
        # test={
        #    'domain': "[('id','in', ["+','.join(map(str,created))+"])]",
        #    'name': 'Contrats',
        #    'view_type': 'form',
        #    'view_mode': 'tree,form',
        #    'res_model': 'hr.salary.proposal',
        #    'view_id': False,
        #    'type': 'ir.actions.act_window',
        # }
        
        # if test:
        #    raise osv.except_osv(_('test'), _('%s')%test)
        ##################################################

        return {
            'domain': "[('id','in', [" + ','.join(map(str, created)) + "])]",
            'name': 'Contrats',
            'view_type': 'form',
            'view_mode': 'tree,form',
            'res_model': 'hr.salary.proposal',
            'view_id': False,
            'type': 'ir.actions.act_window',
        }

        
    def _from_date(self, cursor, user, context={}):
        return datetime.date.today().strftime('%Y-%m-%d');


    _defaults = {
        'date': _from_date, }
Exemplo n.º 20
0
     return resu
 _columns = {
     'employee_id': fields.many2one('hr.employee',  'Employee', required=True, select=True),
     'department_id':fields.related('employee_id','department_id', type='many2one', relation='hr.department', string='Department', store=True),
     'job_id':fields.related('employee_id','job_id', type='many2one', relation='hr.job', string='Title', store=True),
     'emp_code':fields.related('employee_id','emp_code', type='char', string='Employee Code', store=True),
     'mobile_phone':fields.related('employee_id','mobile_phone', type='char', string='Work Mobile', store=True),
     'borrow_money_residual':fields.related('employee_id','money_residual', type='float', string='Borrowed residual', readonly=True),
     
     'dimmission_reason':fields.text('Dimission Reason', required=True),
     'advice_to_company':fields.text('Advice to company'),
     'employment_start':fields.date('Employment Started'),
     'date_request':fields.date('Request Date', required=True),
     'date_done':fields.date('Done Date', required=False, readonly=True),
     
     'approve_ids': fields.one2many('hr.dimission.item', 'dimission_id', 'Approvals', domain=[('type','=','approve')]),
     'transfer_ids': fields.one2many('hr.dimission.item', 'dimission_id', 'Transfers', domain=[('type','=','transfer')]),
     
     'payslip_id': fields.many2many('hr.emppay', string='Payslip'),
     'attrpt_ids': fields.many2many('hr.rpt.attend.month', string='Attendance Reports'),
     'hr_clock_ids': fields.function(_emp_clocks, string='HR Clocks', type='many2many', relation='hr.clock', readonly=True),
     'attachment_lines': fields.one2many('ir.attachment', 'hr_admission_id','Attachment'),    
     'company_id':fields.many2one('res.company', 'Company', required=True),   
                                                  
     'state': fields.selection([
         ('draft', 'Draft'),
         ('in_progress', 'In Progress'),
         ('done', 'Done'),
         ('cancel', 'Cancel'),
     ], 'Status', select=True, readonly=True),
 }
Exemplo n.º 21
0
class hr_salary_proposal(osv.osv):

    _name = "hr.salary.proposal"
    _description = "Proposition de salaire"
    _columns = {
        'date':fields.date('Date'),
        'name': fields.many2one('account.period', 'Periode applicable', required=True),
        'start': fields.many2one('account.period', 'Periode effet'),
        'salary_line':fields.one2many('hr.salary.proposal.line', 'proposal_id', 'Nouvelle Grille'),

        }
    _order = "name desc"

    def validate (self, cr, uid, ids, context=None):
        """ Function doc """
        contract_obj = self.pool.get('hr.contract')
        rubrique_obj = self.pool.get('hr.payroll_ma.ligne_rubrique')
        salary_line_obj = self.pool.get('hr.salary.proposal.line')
        rubrique_objt = self.pool.get('hr.payroll_ma.rubrique')  # new line
        diff = 1
        for proposal in self.browse(cr, uid, ids):
            for line in proposal.salary_line:
                date_start = datetime.datetime.strptime(proposal.name.date_start, '%Y-%m-%d')
                # _logger.info(line.contract_id.rubrique_ids)
                contract_info = contract_obj.copy(cr, uid, line.contract_id.id,
                default={'date_start':date_start, 'wage':line.salary_proposal})
                perc = {}
                amt = {}
                rubriques = []
                for rub in line.rubrique_ids:
                    perc[rub.name.id] = rub.perc_increase
                    amt[rub.name.id] = rub.amount_increase
                    rubriques.append(rub.name.id)
                for rubrique in line.contract_id.rubrique_ids:                    
                    if rubrique.rubrique_id.id in rubriques:
                        amount = rubrique.montant + (rubrique.montant * perc[rubrique.rubrique_id.id] / 100) + amt[rubrique.rubrique_id.id]
                        amount_arrondi = int(amount / 10)  # * 10
                        reste_arrondi = amount % 10
                        if reste_arrondi >= 5:
                            amount_arrondi += 1
                        amount_arrondi = amount_arrondi * 10
                        amount = amount_arrondi
                        amount_diff = amount - rubrique.montant
                        rubrique_obj.copy(cr, uid, rubrique.id, default={'id_contract':contract_info, 'montant':amount, })
                        if proposal.start:
                            date1 = datetime.datetime.strptime(proposal.start.date_start, '%Y-%m-%d')
                            date2 = datetime.datetime.strptime(proposal.name.date_start, '%Y-%m-%d')
                            r = relativedelta.relativedelta(date2, date1)
                            diff = r.months
                            amount = amount_diff * diff
                            rubrique_obj.copy(cr, uid, rubrique.id,
                                default={'rubrique_id':rubrique.rubrique_id.rappel_rubrique_id.id,
                                        'id_contract':contract_info,
                                        'montant':amount, 'permanent':False,
                                        'date_stop':datetime.datetime.strptime(proposal.name.date_stop, '%Y-%m-%d'),
                                        'date_start':datetime.datetime.strptime(proposal.name.date_start, '%Y-%m-%d')
                                        })
                    else:
                        rubrique_obj.copy(cr, uid, rubrique.id, default={'id_contract':contract_info})
                # rappel saleire de base si il y avait augmentation
                # rubrique_obj.copy(cr,uid,rubrique.id,
                #                 default={ 'rubrique_id':rubrique.rubrique_id.rappel_rubrique_id.id,
                #                 'id_contract':contract_info,'montant':amount,'permanent':False,
                #                 'date_stop':datetime.datetime.strptime(proposal.name.date_stop,'%Y-%m-%d'),
                #                 'date_start':datetime.datetime.strptime(proposal.name.date_start,'%Y-%m-%d')})
                ################################################################################################
                T = False
                if line.wage != line.salary_proposal:
                    T = True
                if T:
                    # rubrique_objt = self.pool.get('hr.payroll_ma.rubrique')
                    rubrique_id = rubrique_objt.search(cr, uid, [('code', '=', '02')])  # id du rubrique rappel base
                    if len(rubrique_id) == 0:
                        raise osv.except_osv(_('Error'), _('This rubrique doesn\'t exist! \n create it! His code is: 02'))
                    amount = line.wage * (line.perc_increase / 100) * diff
                    new_rub_base = rubrique_obj.create(cr, uid, {'rubrique_id':rubrique_id[0],
                        'id_contract':contract_info,
                        'montant':amount, 'permanent':False,
                        'date_stop':datetime.datetime.strptime(proposal.name.date_stop, '%Y-%m-%d'),
                        'date_start':datetime.datetime.strptime(proposal.name.date_start, '%Y-%m-%d')})
                ################################################################################################
                new_contract = contract_info
                salary_line_obj.write(cr, uid, line.id, {'new_contract_id':new_contract})
Exemplo n.º 22
0
 ),
 "product_uom": fields.many2one(
     "product.uom", "Unit of Measure ", required=True, readonly=True, states={"draft": [("readonly", False)]}
 ),
 "product_uos_qty": fields.float(
     "Quantity (UoS)",
     digits_compute=dp.get_precision("Product UoS"),
     readonly=True,
     states={"draft": [("readonly", False)]},
 ),
 "product_uos": fields.many2one("product.uom", "Product UoS"),
 "product_rent_qty": fields.function(
     _product_rent_qty, string="Rent Quantity", digits_compute=dp.get_precision("Product UoS")
 ),
 "th_weight": fields.float("Weight", readonly=True, states={"draft": [("readonly", False)]}),
 "move_ids": fields.one2many("stock.move", "rent_line_id", "Inventory Moves", readonly=True),
 "state": fields.selection(
     [
         ("draft", "Draft"),
         ("cancel", "Cancelled"),
         ("confirmed", "Waiting Approval"),
         ("accepted", "Approved"),
         ("returned", "Returned"),
         ("done", "Done"),
     ],
     "Status",
     required=True,
     readonly=True,
 ),
 "order_partner_id": fields.related(
     "order_id", "partner_id", type="many2one", relation="res.partner", store=True, string="Customer"
Exemplo n.º 23
0
class account_bank_statement(osv.osv):
    def create(self, cr, uid, vals, context=None):
        if 'line_ids' in vals:
            for idx, line in enumerate(vals['line_ids']):
                line[2]['sequence'] = idx + 1
        return super(account_bank_statement, self).create(cr,
                                                          uid,
                                                          vals,
                                                          context=context)

    def write(self, cr, uid, ids, vals, context=None):
        res = super(account_bank_statement, self).write(cr,
                                                        uid,
                                                        ids,
                                                        vals,
                                                        context=context)
        account_bank_statement_line_obj = self.pool.get(
            'account.bank.statement.line')
        for statement in self.browse(cr, uid, ids, context):
            for idx, line in enumerate(statement.line_ids):
                account_bank_statement_line_obj.write(cr,
                                                      uid, [line.id],
                                                      {'sequence': idx + 1},
                                                      context=context)
        return res

    def _default_journal_id(self, cr, uid, context=None):
        if context is None:
            context = {}
        journal_pool = self.pool.get('account.journal')
        journal_type = context.get('journal_type', False)
        company_id = self.pool.get('res.company')._company_default_get(
            cr, uid, 'account.bank.statement', context=context)
        if journal_type:
            ids = journal_pool.search(cr, uid,
                                      [('type', '=', journal_type),
                                       ('company_id', '=', company_id)])
            if ids:
                return ids[0]
        return False

    def _end_balance(self, cursor, user, ids, name, attr, context=None):
        res = {}
        for statement in self.browse(cursor, user, ids, context=context):
            res[statement.id] = statement.balance_start
            for line in statement.line_ids:
                res[statement.id] += line.amount
        return res

    def _get_period(self, cr, uid, context=None):
        periods = self.pool.get('account.period').find(cr,
                                                       uid,
                                                       context=context)
        if periods:
            return periods[0]
        return False

    def _currency(self, cursor, user, ids, name, args, context=None):
        res = {}
        res_currency_obj = self.pool.get('res.currency')
        res_users_obj = self.pool.get('res.users')
        default_currency = res_users_obj.browse(
            cursor, user, user, context=context).company_id.currency_id
        for statement in self.browse(cursor, user, ids, context=context):
            currency = statement.journal_id.currency
            if not currency:
                currency = default_currency
            res[statement.id] = currency.id
        currency_names = {}
        for currency_id, currency_name in res_currency_obj.name_get(
                cursor, user, [x for x in res.values()], context=context):
            currency_names[currency_id] = currency_name
        for statement_id in res.keys():
            currency_id = res[statement_id]
            res[statement_id] = (currency_id, currency_names[currency_id])
        return res

    def _get_statement(self, cr, uid, ids, context=None):
        result = {}
        for line in self.pool.get('account.bank.statement.line').browse(
                cr, uid, ids, context=context):
            result[line.statement_id.id] = True
        return result.keys()

    _order = "date desc, id desc"
    _name = "account.bank.statement"
    _description = "Bank Statement"
    _inherit = ['mail.thread']
    _columns = {
        'name':
        fields.char(
            'Reference',
            size=64,
            required=True,
            states={'draft': [('readonly', False)]},
            readonly=True,
            help=
            'if you give the Name other then /, its created Accounting Entries Move will be with same name as statement name. This allows the statement entries to have the same references than the statement itself'
        ),  # readonly for account_cash_statement
        'date':
        fields.date('Date',
                    required=True,
                    states={'confirm': [('readonly', True)]},
                    select=True),
        'journal_id':
        fields.many2one('account.journal',
                        'Journal',
                        required=True,
                        readonly=True,
                        states={'draft': [('readonly', False)]}),
        'period_id':
        fields.many2one('account.period',
                        'Period',
                        required=True,
                        states={'confirm': [('readonly', True)]}),
        'balance_start':
        fields.float('Starting Balance',
                     digits_compute=dp.get_precision('Account'),
                     states={'confirm': [('readonly', True)]}),
        'balance_end_real':
        fields.float('Ending Balance',
                     digits_compute=dp.get_precision('Account'),
                     states={'confirm': [('readonly', True)]}),
        'balance_end':
        fields.function(
            _end_balance,
            store={
                'account.bank.statement':
                (lambda self, cr, uid, ids, c={}: ids,
                 ['line_ids', 'move_line_ids',
                  'balance_start'], 10),
                'account.bank.statement.line':
                (_get_statement, ['amount'], 10),
            },
            string="Computed Balance",
            help=
            'Balance as calculated based on Starting Balance and transaction lines'
        ),
        'company_id':
        fields.related('journal_id',
                       'company_id',
                       type='many2one',
                       relation='res.company',
                       string='Company',
                       store=True,
                       readonly=True),
        'line_ids':
        fields.one2many('account.bank.statement.line',
                        'statement_id',
                        'Statement lines',
                        states={'confirm': [('readonly', True)]}),
        'move_line_ids':
        fields.one2many('account.move.line',
                        'statement_id',
                        'Entry lines',
                        states={'confirm': [('readonly', True)]}),
        'state':
        fields.selection(
            [
                ('draft', 'New'),
                ('open', 'Open'),  # used by cash statements
                ('confirm', 'Closed')
            ],
            'Status',
            required=True,
            readonly="1",
            help='When new statement is created the status will be \'Draft\'.\n'
            'And after getting confirmation from the bank it will be in \'Confirmed\' status.'
        ),
        'currency':
        fields.function(_currency,
                        string='Currency',
                        type='many2one',
                        relation='res.currency'),
        'account_id':
        fields.related(
            'journal_id',
            'default_debit_account_id',
            type='many2one',
            relation='account.account',
            string='Account used in this journal',
            readonly=True,
            help=
            'used in statement reconciliation domain, but shouldn\'t be used elswhere.'
        ),
    }

    _defaults = {
        'name':
        "/",
        'date':
        fields.date.context_today,
        'state':
        'draft',
        'journal_id':
        _default_journal_id,
        'period_id':
        _get_period,
        'company_id':
        lambda self, cr, uid, c: self.pool.get('res.company').
        _company_default_get(cr, uid, 'account.bank.statement', context=c),
    }

    def _check_company_id(self, cr, uid, ids, context=None):
        for statement in self.browse(cr, uid, ids, context=context):
            if statement.company_id.id != statement.period_id.company_id.id:
                return False
        return True

    _constraints = [
        (_check_company_id,
         'The journal and period chosen have to belong to the same company.',
         ['journal_id', 'period_id']),
    ]

    def onchange_date(self, cr, uid, ids, date, company_id, context=None):
        """
            Find the correct period to use for the given date and company_id, return it and set it in the context
        """
        res = {}
        period_pool = self.pool.get('account.period')

        if context is None:
            context = {}
        ctx = context.copy()
        ctx.update({'company_id': company_id})
        pids = period_pool.find(cr, uid, dt=date, context=ctx)
        if pids:
            res.update({'period_id': pids[0]})
            context.update({'period_id': pids[0]})

        return {
            'value': res,
            'context': context,
        }

    def button_dummy(self, cr, uid, ids, context=None):
        return self.write(cr, uid, ids, {}, context=context)

    def _prepare_move(self, cr, uid, st_line, st_line_number, context=None):
        """Prepare the dict of values to create the move from a
           statement line. This method may be overridden to implement custom
           move generation (making sure to call super() to establish
           a clean extension chain).

           :param browse_record st_line: account.bank.statement.line record to
                  create the move from.
           :param char st_line_number: will be used as the name of the generated account move
           :return: dict of value to create() the account.move
        """
        return {
            'journal_id': st_line.statement_id.journal_id.id,
            'period_id': st_line.statement_id.period_id.id,
            'date': st_line.date,
            'name': st_line_number,
            'ref': st_line.ref,
        }

    def _prepare_bank_move_line(self,
                                cr,
                                uid,
                                st_line,
                                move_id,
                                amount,
                                company_currency_id,
                                context=None):
        """Compute the args to build the dict of values to create the bank move line from a
           statement line by calling the _prepare_move_line_vals. This method may be
           overridden to implement custom move generation (making sure to call super() to
           establish a clean extension chain).

           :param browse_record st_line: account.bank.statement.line record to
                  create the move from.
           :param int/long move_id: ID of the account.move to link the move line
           :param float amount: amount of the move line
           :param int/long company_currency_id: ID of currency of the concerned company
           :return: dict of value to create() the bank account.move.line
        """
        anl_id = st_line.analytic_account_id and st_line.analytic_account_id.id or False
        debit = ((amount < 0) and -amount) or 0.0
        credit = ((amount > 0) and amount) or 0.0
        cur_id = False
        amt_cur = False
        if st_line.statement_id.currency.id <> company_currency_id:
            cur_id = st_line.statement_id.currency.id
        if st_line.account_id and st_line.account_id.currency_id and st_line.account_id.currency_id.id <> company_currency_id:
            cur_id = st_line.account_id.currency_id.id
        if cur_id:
            res_currency_obj = self.pool.get('res.currency')
            amt_cur = -res_currency_obj.compute(
                cr, uid, company_currency_id, cur_id, amount, context=context)

        res = self._prepare_move_line_vals(cr,
                                           uid,
                                           st_line,
                                           move_id,
                                           debit,
                                           credit,
                                           amount_currency=amt_cur,
                                           currency_id=cur_id,
                                           analytic_id=anl_id,
                                           context=context)
        return res

    def _get_counter_part_account(sefl, cr, uid, st_line, context=None):
        """Retrieve the account to use in the counterpart move.
           This method may be overridden to implement custom move generation (making sure to
           call super() to establish a clean extension chain).

           :param browse_record st_line: account.bank.statement.line record to
                  create the move from.
           :return: int/long of the account.account to use as counterpart
        """
        if st_line.amount >= 0:
            return st_line.statement_id.journal_id.default_credit_account_id.id
        return st_line.statement_id.journal_id.default_debit_account_id.id

    def _get_counter_part_partner(sefl, cr, uid, st_line, context=None):
        """Retrieve the partner to use in the counterpart move.
           This method may be overridden to implement custom move generation (making sure to
           call super() to establish a clean extension chain).

           :param browse_record st_line: account.bank.statement.line record to
                  create the move from.
           :return: int/long of the res.partner to use as counterpart
        """
        return st_line.partner_id and st_line.partner_id.id or False

    def _prepare_counterpart_move_line(self,
                                       cr,
                                       uid,
                                       st_line,
                                       move_id,
                                       amount,
                                       company_currency_id,
                                       context=None):
        """Compute the args to build the dict of values to create the counter part move line from a
           statement line by calling the _prepare_move_line_vals. This method may be
           overridden to implement custom move generation (making sure to call super() to
           establish a clean extension chain).

           :param browse_record st_line: account.bank.statement.line record to
                  create the move from.
           :param int/long move_id: ID of the account.move to link the move line
           :param float amount: amount of the move line
           :param int/long account_id: ID of account to use as counter part
           :param int/long company_currency_id: ID of currency of the concerned company
           :return: dict of value to create() the bank account.move.line
        """
        account_id = self._get_counter_part_account(cr,
                                                    uid,
                                                    st_line,
                                                    context=context)
        partner_id = self._get_counter_part_partner(cr,
                                                    uid,
                                                    st_line,
                                                    context=context)
        debit = ((amount > 0) and amount) or 0.0
        credit = ((amount < 0) and -amount) or 0.0
        cur_id = False
        amt_cur = False
        if st_line.statement_id.currency.id <> company_currency_id:
            amt_cur = st_line.amount
            cur_id = st_line.statement_id.currency.id
        return self._prepare_move_line_vals(cr,
                                            uid,
                                            st_line,
                                            move_id,
                                            debit,
                                            credit,
                                            amount_currency=amt_cur,
                                            currency_id=cur_id,
                                            account_id=account_id,
                                            partner_id=partner_id,
                                            context=context)

    def _prepare_move_line_vals(self,
                                cr,
                                uid,
                                st_line,
                                move_id,
                                debit,
                                credit,
                                currency_id=False,
                                amount_currency=False,
                                account_id=False,
                                analytic_id=False,
                                partner_id=False,
                                context=None):
        """Prepare the dict of values to create the move line from a
           statement line. All non-mandatory args will replace the default computed one.
           This method may be overridden to implement custom move generation (making sure to
           call super() to establish a clean extension chain).

           :param browse_record st_line: account.bank.statement.line record to
                  create the move from.
           :param int/long move_id: ID of the account.move to link the move line
           :param float debit: debit amount of the move line
           :param float credit: credit amount of the move line
           :param int/long currency_id: ID of currency of the move line to create
           :param float amount_currency: amount of the debit/credit expressed in the currency_id
           :param int/long account_id: ID of the account to use in the move line if different
                  from the statement line account ID
           :param int/long analytic_id: ID of analytic account to put on the move line
           :param int/long partner_id: ID of the partner to put on the move line
           :return: dict of value to create() the account.move.line
        """
        acc_id = account_id or st_line.account_id.id
        cur_id = currency_id or st_line.statement_id.currency.id
        par_id = partner_id or ((
            (st_line.partner_id) and st_line.partner_id.id) or False)
        return {
            'name': st_line.name,
            'date': st_line.date,
            'ref': st_line.ref,
            'move_id': move_id,
            'partner_id': par_id,
            'account_id': acc_id,
            'credit': credit,
            'debit': debit,
            'statement_id': st_line.statement_id.id,
            'journal_id': st_line.statement_id.journal_id.id,
            'period_id': st_line.statement_id.period_id.id,
            'currency_id': amount_currency and cur_id,
            'amount_currency': amount_currency,
            'analytic_account_id': analytic_id,
        }

    def create_move_from_st_line(self,
                                 cr,
                                 uid,
                                 st_line_id,
                                 company_currency_id,
                                 st_line_number,
                                 context=None):
        """Create the account move from the statement line.

           :param int/long st_line_id: ID of the account.bank.statement.line to create the move from.
           :param int/long company_currency_id: ID of the res.currency of the company
           :param char st_line_number: will be used as the name of the generated account move
           :return: ID of the account.move created
        """

        if context is None:
            context = {}
        res_currency_obj = self.pool.get('res.currency')
        account_move_obj = self.pool.get('account.move')
        account_move_line_obj = self.pool.get('account.move.line')
        account_bank_statement_line_obj = self.pool.get(
            'account.bank.statement.line')
        st_line = account_bank_statement_line_obj.browse(cr,
                                                         uid,
                                                         st_line_id,
                                                         context=context)
        st = st_line.statement_id

        context.update({'date': st_line.date})

        move_vals = self._prepare_move(cr,
                                       uid,
                                       st_line,
                                       st_line_number,
                                       context=context)
        move_id = account_move_obj.create(cr, uid, move_vals, context=context)
        account_bank_statement_line_obj.write(
            cr, uid, [st_line.id], {'move_ids': [(4, move_id, False)]})
        torec = []
        acc_cur = (
            (st_line.amount <= 0)
            and st.journal_id.default_debit_account_id) or st_line.account_id

        context.update({
            'res.currency.compute.account': acc_cur,
        })
        amount = res_currency_obj.compute(cr,
                                          uid,
                                          st.currency.id,
                                          company_currency_id,
                                          st_line.amount,
                                          context=context)

        bank_move_vals = self._prepare_bank_move_line(cr,
                                                      uid,
                                                      st_line,
                                                      move_id,
                                                      amount,
                                                      company_currency_id,
                                                      context=context)
        move_line_id = account_move_line_obj.create(cr,
                                                    uid,
                                                    bank_move_vals,
                                                    context=context)
        torec.append(move_line_id)

        counterpart_move_vals = self._prepare_counterpart_move_line(
            cr,
            uid,
            st_line,
            move_id,
            amount,
            company_currency_id,
            context=context)
        account_move_line_obj.create(cr,
                                     uid,
                                     counterpart_move_vals,
                                     context=context)

        for line in account_move_line_obj.browse(
                cr,
                uid, [
                    x.id for x in account_move_obj.browse(
                        cr, uid, move_id, context=context).line_id
                ],
                context=context):
            if line.state <> 'valid':
                raise osv.except_osv(
                    _('Error!'),
                    _('Journal item "%s" is not valid.') % line.name)

        # Bank statements will not consider boolean on journal entry_posted
        account_move_obj.post(cr, uid, [move_id], context=context)
        return move_id

    def get_next_st_line_number(self,
                                cr,
                                uid,
                                st_number,
                                st_line,
                                context=None):
        return st_number + '/' + str(st_line.sequence)

    def balance_check(self, cr, uid, st_id, journal_type='bank', context=None):
        st = self.browse(cr, uid, st_id, context=context)
        if not ((abs((st.balance_end or 0.0) - st.balance_end_real) < 0.0001)
                or
                (abs((st.balance_end or 0.0) - st.balance_end_real) < 0.0001)):
            raise osv.except_osv(
                _('Error!'),
                _('The statement balance is incorrect !\nThe expected balance (%.2f) is different than the computed one. (%.2f)'
                  ) % (st.balance_end_real, st.balance_end))
        return True

    def statement_close(self, cr, uid, ids, journal_type='bank', context=None):
        return self.write(cr, uid, ids, {'state': 'confirm'}, context=context)

    def check_status_condition(self, cr, uid, state, journal_type='bank'):
        return state in ('draft', 'open')

    def button_confirm_bank(self, cr, uid, ids, context=None):
        obj_seq = self.pool.get('ir.sequence')
        if context is None:
            context = {}

        for st in self.browse(cr, uid, ids, context=context):
            j_type = st.journal_id.type
            company_currency_id = st.journal_id.company_id.currency_id.id
            if not self.check_status_condition(
                    cr, uid, st.state, journal_type=j_type):
                continue

            self.balance_check(cr,
                               uid,
                               st.id,
                               journal_type=j_type,
                               context=context)
            if (not st.journal_id.default_credit_account_id) \
                    or (not st.journal_id.default_debit_account_id):
                raise osv.except_osv(
                    _('Configuration Error!'),
                    _('Please verify that an account is defined in the journal.'
                      ))

            if not st.name == '/':
                st_number = st.name
            else:
                c = {'fiscalyear_id': st.period_id.fiscalyear_id.id}
                if st.journal_id.sequence_id:
                    st_number = obj_seq.next_by_id(
                        cr, uid, st.journal_id.sequence_id.id, context=c)
                else:
                    st_number = obj_seq.next_by_code(cr,
                                                     uid,
                                                     'account.bank.statement',
                                                     context=c)

            for line in st.move_line_ids:
                if line.state <> 'valid':
                    raise osv.except_osv(
                        _('Error!'),
                        _('The account entries lines are not in valid state.'))
            for st_line in st.line_ids:
                if st_line.analytic_account_id:
                    if not st.journal_id.analytic_journal_id:
                        raise osv.except_osv(
                            _('No Analytic Journal!'),
                            _("You have to assign an analytic journal on the '%s' journal!"
                              ) % (st.journal_id.name, ))
                if not st_line.amount:
                    continue
                st_line_number = self.get_next_st_line_number(
                    cr, uid, st_number, st_line, context)
                self.create_move_from_st_line(cr, uid, st_line.id,
                                              company_currency_id,
                                              st_line_number, context)

            self.write(cr,
                       uid, [st.id], {
                           'name': st_number,
                           'balance_end_real': st.balance_end
                       },
                       context=context)
            self.message_post(
                cr,
                uid, [st.id],
                body=_('Statement %s confirmed, journal items were created.') %
                (st_number, ),
                context=context)
        return self.write(cr, uid, ids, {'state': 'confirm'}, context=context)

    def button_cancel(self, cr, uid, ids, context=None):
        done = []
        account_move_obj = self.pool.get('account.move')
        for st in self.browse(cr, uid, ids, context=context):
            if st.state == 'draft':
                continue
            move_ids = []
            for line in st.line_ids:
                move_ids += [x.id for x in line.move_ids]
            account_move_obj.button_cancel(cr, uid, move_ids, context=context)
            account_move_obj.unlink(cr, uid, move_ids, context)
            done.append(st.id)
        return self.write(cr, uid, done, {'state': 'draft'}, context=context)

    def _compute_balance_end_real(self, cr, uid, journal_id, context=None):
        res = False
        if journal_id:
            cr.execute(
                'SELECT balance_end_real \
                    FROM account_bank_statement \
                    WHERE journal_id = %s AND NOT state = %s \
                    ORDER BY date DESC,id DESC LIMIT 1', (journal_id, 'draft'))
            res = cr.fetchone()
        return res and res[0] or 0.0

    def onchange_journal_id(self,
                            cr,
                            uid,
                            statement_id,
                            journal_id,
                            context=None):
        if not journal_id:
            return {}
        balance_start = self._compute_balance_end_real(cr,
                                                       uid,
                                                       journal_id,
                                                       context=context)

        journal_data = self.pool.get('account.journal').read(
            cr, uid, journal_id, ['company_id', 'currency'], context=context)
        company_id = journal_data['company_id']
        currency_id = journal_data['currency'] or self.pool.get(
            'res.company').browse(cr, uid, company_id[0],
                                  context=context).currency_id.id
        return {
            'value': {
                'balance_start': balance_start,
                'company_id': company_id,
                'currency': currency_id
            }
        }

    def unlink(self, cr, uid, ids, context=None):
        stat = self.read(cr, uid, ids, ['state'], context=context)
        unlink_ids = []
        for t in stat:
            if t['state'] in ('draft'):
                unlink_ids.append(t['id'])
            else:
                raise osv.except_osv(
                    _('Invalid Action!'),
                    _('In order to delete a bank statement, you must first cancel it to delete related journal items.'
                      ))
        osv.osv.unlink(self, cr, uid, unlink_ids, context=context)
        return True

    def copy(self, cr, uid, id, default=None, context=None):
        if default is None:
            default = {}
        if context is None:
            context = {}
        default = default.copy()
        default['move_line_ids'] = []
        return super(account_bank_statement, self).copy(cr,
                                                        uid,
                                                        id,
                                                        default,
                                                        context=context)

    def button_journal_entries(self, cr, uid, ids, context=None):
        ctx = (context or {}).copy()
        ctx['journal_id'] = self.browse(cr, uid, ids[0],
                                        context=context).journal_id.id
        return {
            'view_type': 'form',
            'view_mode': 'tree',
            'res_model': 'account.move.line',
            'view_id': False,
            'type': 'ir.actions.act_window',
            'domain': [('statement_id', 'in', ids)],
            'context': ctx,
        }
Exemplo n.º 24
0
    ('boolean', fields.boolean()),
    ('integer', fields.integer()),
    ('float', fields.float()),
    ('decimal', fields.float(digits=(16, 3))),
    ('string.bounded', fields.char('unknown', size=16)),
    ('string.required', fields.char('unknown', size=None, required=True)),
    ('string', fields.char('unknown', size=None)),
    ('date', fields.date()),
    ('datetime', fields.datetime()),
    ('text', fields.text()),
    ('selection', fields.selection([(1, "Foo"), (2, "Bar"), (3, "Qux"), (4, '')])),
    # here use size=-1 to store the values as integers instead of strings
    ('selection.function', fields.selection(selection_fn, size=-1)),
    # just relate to an integer
    ('many2one', fields.many2one('export.integer')),
    ('one2many', fields.one2many('export.one2many.child', 'parent_id')),
    ('many2many', fields.many2many('export.many2many.other')),
    ('function', fields.function(function_fn, fnct_inv=function_fn_write, type="integer")),
    # related: specialization of fields.function, should work the same way
    # TODO: reference
]

for name, field in models:
    class NewModel(orm.Model):
        _name = 'export.%s' % name
        _columns = {
            'const': fields.integer(),
            'value': field,
        }
        _defaults = {
            'const': 4,
Exemplo n.º 25
0
class rhwl_config(osv.osv):
    _name = "rhwl.weixin.base"

    _columns = {
        "name":
        fields.char("Name", size=20),
        "original_id":
        fields.char("Original ID", size=20),
        "code":
        fields.char("Code", size=10),
        "token_flag":
        fields.char(u"Token(令牌)", size=10),
        "appid":
        fields.char("AppID"),
        "appsecret":
        fields.char("AppSecret"),
        "token":
        fields.char("Token", readonly=True),
        "token_create":
        fields.datetime("TokenCreate", readonly=True),
        "expires_in":
        fields.integer("Expires_IN", readonly=True),
        "user_menu":
        fields.text("User Menu"),
        "ticket":
        fields.char("Ticket", readonly=True),
        "ticket_create":
        fields.datetime("TicketCreate", readonly=True),
        "ticket_expires":
        fields.integer("Ticket Expires", readonly=True),
        "welcome":
        fields.text("Welcome"),
        "users":
        fields.one2many("rhwl.weixin", "base_id", u"关注用户"),
        "menu":
        fields.one2many("rhwl.weixin.usermenu", "base_id", u"自定义菜单"),
        "is_valid":
        fields.boolean(u"已认证"),
        "service_type":
        fields.selection([("1", u"订阅号"), ("2", u"服务号"), ("3", u"企业号")],
                         u"帐号类型")
    }

    def _get_memcache(self, key):
        return MEMCACHE.get(key, None)

    def _set_memcache(self, key, val):
        MEMCACHE[key] = val

    def _get_memcache_id(self, cr, original, AgentID):
        ids = self._get_memcache((original, AgentID))
        if not ids:
            if (not AgentID) or AgentID == "0":
                ids = self.search(cr, SUPERUSER_ID,
                                  [("original_id", "=", original)])
            else:
                ids = self.search(cr, SUPERUSER_ID,
                                  [("original_id", "=", original),
                                   ("appid", "=", AgentID)])
            self._set_memcache((original, AgentID), ids)
        return ids

    #用户关注时,记录用户的OpenId信息,并返回设置的欢迎文字
    def action_subscribe(self, cr, original, fromUser, AgentID="0"):
        origId = self._get_memcache_id(cr, original, AgentID)
        user = self.pool.get('rhwl.weixin')

        for o in origId:
            id = user.search(cr, SUPERUSER_ID, [("base_id", "=", o),
                                                ('openid', '=', fromUser), '|',
                                                ('active', '=', False),
                                                ("active", "=", True)])

            if id:
                user.write(cr, SUPERUSER_ID, id, {"active": True})
            else:
                user.create(
                    cr, SUPERUSER_ID, {
                        "base_id": o,
                        'openid': fromUser,
                        'active': True,
                        'state': 'draft'
                    })
        cr.commit()
        obj = self.browse(cr, SUPERUSER_ID, origId[0])
        return obj.welcome

    def action_unsubscribe(self, cr, original, fromUser, AgentID="0"):
        origId = self._get_memcache_id(cr, original, AgentID)
        user = self.pool.get('rhwl.weixin')
        for o in origId:
            id = user.search(cr, SUPERUSER_ID, [("base_id", "=", o),
                                                ('openid', '=', fromUser)])
            if id:
                user.write(cr, SUPERUSER_ID, id, {"active": False})
        cr.commit()

    def action_event_clicked(self, cr, key, original, fromUser, appid=None):
        origId = self._get_memcache_id(cr, original, appid)
        obj = self.browse(cr, SUPERUSER_ID, origId)
        if obj.code == "rhwc" and key == "ONLINE_QUERY":
            return u"请您输入送检编号!"
        articles = self._get_htmlmsg(cr, origId[0], key)
        _logger.debug(articles)
        if articles[0]:
            userid = self._get_userid(cr, origId[0], fromUser)
            if not userid:
                articles = {
                    "Title": "内部ERP帐号绑定",
                    "Description": "您查阅的功能需要授权,请先进行内部ERP帐号绑定",
                    "PicUrl": "/rhwl_weixin/static/img/logo1.png",
                    "Url": "/rhwl_weixin/static/weixinbind.html"
                }
                return (obj.code.encode("utf-8"), [
                    articles,
                ])
            if articles[1]:
                is_has_group = False

                uobj = self.pool.get("res.users")
                for i in articles[1].split(","):
                    is_has_group = uobj.has_group(cr, userid, i)
                    if is_has_group: break
                if not is_has_group:
                    articles = {
                        "Title": "访问权限不足",
                        "Description": "您查阅的功能需要特别授权,请与管理员联系。",
                        "PicUrl": "/rhwl_weixin/static/img/logo1.png",
                    }
                    return (obj.code.encode("utf-8"), [
                        articles,
                    ])
        _logger.debug(articles[2])
        if articles[2]:
            return (obj.code.encode("utf-8"), articles[2])
        else:
            return u"此功能在开发中,敬请稍候!"

    def action_text_input(self, cr, content, original, fromUser):
        origId = self._get_memcache_id(cr, original, None)
        obj = self.browse(cr, SUPERUSER_ID, origId)

        if obj.code == "rhwc":  #人和无创公众号
            sample = self.pool.get("sale.sampleone")
            user = self.pool.get('rhwl.weixin')

            if content.isalnum() and len(content) == 6:
                id = user.search(cr, SUPERUSER_ID,
                                 [("base_id", "=", origId[0]),
                                  ("active", '=', True),
                                  ("state", "=", "process"),
                                  ("checkNum", "=", content)])
                if not id:
                    return u"请先输入样品编码。"
                else:
                    obj = user.browse(cr, SUPERUSER_ID, id)
                    mindate = datetime.datetime.utcnow() - datetime.timedelta(
                        minutes=5)
                    if obj.checkDateTime < mindate.strftime(
                            "%Y-%m-%d %H:%M:%S"):
                        return u"验证码已过期,请重新输入样品编码查询。"
                    else:
                        id = sample.search(cr, SUPERUSER_ID,
                                           [("name", "=", obj.sampleno)])
                        sample_obj = sample.browse(cr, SUPERUSER_ID, id)
                        user.write(cr, SUPERUSER_ID, obj.id, {"state": "pass"})
                        cr.commit()
                        return u"您的样品编码" + obj.sampleno + u"目前进度为【" + rhwl_sale.rhwl_sale_state_select.get(
                            sample_obj.check_state) + u"】,完成后详细的检测报告请与检测医院索取。"
            else:
                id = sample.search(cr, SUPERUSER_ID, [('name', '=', content)])

                if id:
                    openid = user.search(cr, SUPERUSER_ID,
                                         [('openid', '=', fromUser)])
                    obj = sample.browse(cr, SUPERUSER_ID, id)
                    rand = random.randint(111111, 999999)
                    checkDateTime = datetime.datetime.utcnow()
                    user.write(
                        cr, SUPERUSER_ID, openid, {
                            "telno": obj.yftelno,
                            "state": "process",
                            "checkNum": rand,
                            "checkDateTime": checkDateTime,
                            "sampleno": content
                        })
                    cr.commit()
                    if obj.yftelno:
                        self.pool.get("res.company").send_sms(
                            cr, SUPERUSER_ID, obj.yftelno,
                            u"您查询样品检测结果的验证码为%s,请在五分钟内输入,如果不是您本人操作,请不用处理。" %
                            (rand, ))
                        return u"验证码已经发送至检测知情同意书上登记的电话" + obj.yftelno[:3] + u"****" + obj.yftelno[
                            -4:] + u",请收到验证码后在五分钟内输入。"
                    else:
                        return u"您查询的样品编码在检测知情同意书上没有登记电话,不能发送验证码,请与送检医院查询结果。"
                else:
                    #if re.search("[^0-9a-zA-Z]",content):
                    #    return self.customer_service(fromUser,toUser)
                    #else:
                    return u"您所查询的样品编码[%s]不存在,请重新输入,输入时注意区分大小写字母,并去掉多余的空格!" % (
                        content)

        else:
            return u"欢迎光临"

    def _get_htmlmsg(self, cr, orig_id, key):
        msg = self.pool.get("rhwl.weixin.usermenu2")

        id = msg.search(cr, SUPERUSER_ID, [("parent.base_id.id", "=", orig_id),
                                           ("key", "=", key)])
        if not id:
            return (False, "", None)
        obj = msg.browse(cr, SUPERUSER_ID, id)
        if not obj.htmlmsg:
            return (obj.need_user, obj.groups, None)
        articles = []
        for j in obj.htmlmsg:
            val = {
                "Title": j.title.encode("utf-8"),
                "Description": j.description.encode("utf-8"),
                "PicUrl": j.picurl.encode("utf-8"),
            }
            if j.url:
                val["Url"] = j.url and j.url.encode("utf-8") or ""
            articles.append(val)
        return (obj.need_user, obj.groups, articles)

    def _get_userid(self, cr, orig_id, openid):
        weixin = self.pool.get("rhwl.weixin")

        id = weixin.search(cr, SUPERUSER_ID, [("base_id", "=", orig_id), '|',
                                              ('openid', '=', openid),
                                              ("rhwlid", "=", openid)])
        if id:
            obj = weixin.browse(cr, SUPERUSER_ID, id)
            return obj.user_id.id
        return None

    def _get_ticket(self, cr, uid, val, valType="code", context=None):
        arg = {"access_token": "", "type": "jsapi"}
        ids = self.search(cr, uid, [(valType, "=", val)], limit=1)
        obj = self.browse(cr, uid, ids, context=context)
        if not obj.ticket or (
                datetime.datetime.now() - datetime.datetime.strptime(
                    obj.ticket_create, tools.DEFAULT_SERVER_DATETIME_FORMAT)
        ).total_seconds() > (obj.ticket_expires - 30):
            arg['access_token'] = self._get_token(cr,
                                                  uid,
                                                  val,
                                                  valType,
                                                  obj,
                                                  context=context)
            if obj.service_type == "3":
                s = requests.post(
                    "https://qyapi.weixin.qq.com/cgi-bin/get_jsapi_ticket",
                    params=arg)
            else:
                s = requests.post(
                    "https://api.weixin.qq.com/cgi-bin/ticket/getticket",
                    params=arg)
            ref = s.content
            s.close()
            res = eval(ref)
            if res.get("errcode") == 0:
                self.write(
                    cr, uid, obj.id, {
                        "ticket": res.get("ticket"),
                        "ticket_create": fields.datetime.now(),
                        "ticket_expires": res.get("expires_in")
                    })
            else:
                raise osv.except_osv("错误", res.get("errmsg"))
            return res.get("ticket")
        elif obj.token:
            return obj.ticket.encode('utf-8')

    def _get_token(self, cr, uid, val, valType="code", obj=None, context=None):
        arg = {
            "grant_type": "client_credential",
            "appid": "",
            "secret": "",
        }
        arg_qy = {"corpid": "", "corpsecret": ""}

        if not obj:
            ids = self.search(cr, uid, [(valType, "=", val)], limit=1)
            obj = self.browse(cr, uid, ids, context=context)

        if obj.service_type == "3":
            #企业号处理
            if (not obj.token
                ) or (datetime.datetime.now() - datetime.datetime.strptime(
                    obj.token_create, tools.DEFAULT_SERVER_DATETIME_FORMAT)
                      ).total_seconds() > (obj.expires_in - 30):
                arg_qy["corpid"] = obj.original_id
                arg_qy["corpsecret"] = obj.appsecret
                s = requests.post(
                    "https://qyapi.weixin.qq.com/cgi-bin/gettoken",
                    params=arg_qy)
                ref = s.content
                s.close()
                res = eval(ref)
                if res.get("access_token"):
                    self.write(
                        cr, uid, obj.id, {
                            "token": res.get("access_token"),
                            "token_create": fields.datetime.now(),
                            "expires_in": res.get("expires_in")
                        })
                else:
                    raise osv.except_osv("错误", res.get("errmsg"))
                return res.get("access_token")
            else:
                return obj.token.encode('utf-8')
        else:
            if (not obj.token
                ) or (datetime.datetime.now() - datetime.datetime.strptime(
                    obj.token_create, tools.DEFAULT_SERVER_DATETIME_FORMAT)
                      ).total_seconds() > (obj.expires_in - 30):
                arg["appid"] = obj.appid
                arg["secret"] = obj.appsecret
                s = requests.post("https://api.weixin.qq.com/cgi-bin/token",
                                  params=arg)
                ref = s.content
                s.close()
                res = eval(ref)
                if res.get("access_token"):
                    self.write(
                        cr, uid, obj.id, {
                            "token": res.get("access_token"),
                            "token_create": fields.datetime.now(),
                            "expires_in": res.get("expires_in")
                        })
                else:
                    raise osv.except_osv("错误", res.get("errmsg"))
                _logger.info("Get New Token:" + res.get("access_token"))
                return res.get("access_token")
            elif obj.token:
                _logger.info("Get Old Token:" + obj.token.encode('utf-8'))
                return obj.token.encode('utf-8')

    def action_token(self, cr, uid, ids, context=None):
        for i in self.browse(cr, uid, ids, context=context):
            self._get_token(cr, uid, None, None, i, context)

    def _get_menu_detail_json(self, cr, uid, ids, context=None):
        d = {
            "sub_button": [],
        }
        obj = self.pool.get("rhwl.weixin.usermenu").browse(cr,
                                                           uid,
                                                           ids,
                                                           context=context)
        if obj.details:
            d["name"] = obj.name.encode('utf-8')
            for i in obj.details:
                dic = {
                    "type": i.type.encode('utf-8'),
                    "name": i.name.encode('utf-8'),
                }
                if i.type == "view":
                    dic["url"] = i.url.encode('utf-8')
                elif i.type == "click":
                    dic["key"] = i.key.encode('utf-8')

                d['sub_button'].append(dic)
            return d
        else:
            d = {}
            d["type"] = obj.type.encode('utf-8')
            d["name"] = obj.name.encode('utf-8')
            if obj.type == "view": d["url"] = obj.url.encode('utf-8')
            if obj.type == "click": d["key"] = obj.key.encode('utf-8')
            return d

    def _get_menu_json(self, cr, uid, id, context=None):
        m = {
            "button": [],
        }
        ids = self.pool.get("rhwl.weixin.usermenu").search(
            cr, uid, [("base_id", "=", id)], context=context)
        if not ids:
            raise osv.except_osv(u"错误", u"您还没有配置用户自定义菜单内容。")

        if isinstance(ids, (long, int)):
            ids = [
                ids,
            ]
        for i in ids:
            m['button'].append(
                self._get_menu_detail_json(cr, uid, i, context=context))
        return m

    def action_usermenu(self, cr, uid, ids, context=None):
        args = {}

        for i in self.browse(cr, uid, ids, context=context):
            if i.service_type == "3":
                create_url = "https://qyapi.weixin.qq.com/cgi-bin/menu/create"
                args["access_token"] = self._get_token(cr, uid, None, None, i,
                                                       context)
                args["agentid"] = i.appid
            else:
                create_url = "https://api.weixin.qq.com/cgi-bin/menu/create"
                args["access_token"] = self._get_token(cr, uid, None, None, i,
                                                       context)
            i.user_menu = str(
                self._get_menu_json(cr, uid, i.id, context=context))

            s = requests.post(
                create_url,
                params=args,
                data=json.dumps(eval(i.user_menu), ensure_ascii=False),
                headers={'content-type': 'application/json; encoding=utf-8'},
                allow_redirects=False)
            ref = s.content
            s.close()
            res = eval(ref)
            if res.get("errcode") != 0:
                raise osv.except_osv("错误" + str(res.get("errcode")),
                                     res.get("errmsg"))

    def send_template1(self, cr, uid, to_user, json_dict, context=None):
        id = self.pool.get("rhwl.weixin").search(
            cr, SUPERUSER_ID, [("base_id.code", "=", "rhwc"),
                               ("user_id", "=", to_user)])
        if not id: return
        id = id[0]
        obj = self.pool.get("rhwl.weixin").browse(cr, SUPERUSER_ID, id)
        json_dict["touser"] = obj.openid.encode('utf-8')
        if json_dict["url"]:
            json_dict["url"] += "?openid=" + obj.openid.encode('utf-8')
        token = self._get_token(cr, SUPERUSER_ID, "rhwc", context=context)
        s = requests.post(
            "https://api.weixin.qq.com/cgi-bin/message/template/send",
            params={"access_token": token},
            data=json.dumps(json_dict, ensure_ascii=False),
            headers={'content-type': 'application/json; encoding=utf-8'},
            allow_redirects=False)
        ref = s.content
        s.close()

    def send_template2(self, cr, uid, json_dict, col, context=None):
        template = {
            "touser": "******",
            "template_id": "D2fDRIhwFe9jpHgLtTjkRy5jOz_AqQnvuGzpYQFkgRs",
            "url": "",
            "topcolor": "#FF0000",
            "data": {
                "first": {
                    "value": json_dict["first"],
                    "color": "#173177"
                },
                "keyword1": {
                    "value": json_dict["keyword1"],
                    "color": "#173177"
                },
                "keyword2": {
                    "value": json_dict["keyword2"],
                    "color": "#173177"
                },
                "keyword3": {
                    "value": json_dict["keyword3"],
                    "color": "#173177"
                },
                "remark": {
                    "value": json_dict["remark"],
                    "color": "#173177"
                }
            }
        }
        id = self.pool.get("rhwl.weixin").search(cr, SUPERUSER_ID,
                                                 [(col, "=", True)])
        for i in id:
            obj = self.pool.get("rhwl.weixin").browse(cr,
                                                      SUPERUSER_ID,
                                                      i,
                                                      context=context)
            token = self._get_token(cr, SUPERUSER_ID, "rhwc", context=context)
            template["touser"] = obj.openid.encode('utf-8')

            s = requests.post(
                "https://api.weixin.qq.com/cgi-bin/message/template/send",
                params={"access_token": token},
                data=json.dumps(template, ensure_ascii=False),
                headers={'content-type': 'application/json; encoding=utf-8'},
                allow_redirects=False)
            ref = s.content
            s.close()

    def send_qy_text_ids(self, cr, uid, ids, content, context=None):
        vals = {
            "touser": "",
            "toparty": "",
            "totag": "",
            "msgtype": "text",
            "agentid": None,
            "text": {
                "content": ""
            },
            "safe": "0"
        }
        touser = []
        if ids:
            for i in self.pool.get("rhwl.weixin").browse(cr,
                                                         uid,
                                                         ids,
                                                         context=context):
                touser.append(i.openid.encode('utf-8'))
                if not vals["agentid"]:
                    vals["agentid"] = i.base_id.appid.encode('utf-8')
                    token = self._get_token(cr,
                                            SUPERUSER_ID,
                                            i.base_id.code.encode('utf-8'),
                                            context=context)
            vals["touser"] = '******'.join(touser)
            vals["text"]["content"] = content.encode('utf-8')
            #_logger.error(vals)
            s = requests.post(
                "https://qyapi.weixin.qq.com/cgi-bin/message/send",
                params={"access_token": token},
                data=json.dumps(vals, ensure_ascii=False),
                headers={'content-type': 'application/json; encoding=utf-8'},
                allow_redirects=False)
            ref = s.content
            s.close()

    def send_qy_text_openid(self,
                            cr,
                            uid,
                            code,
                            openid,
                            content,
                            context=None):
        ids = self.pool.get("rhwl.weixin").search(cr,
                                                  uid,
                                                  [("base_id.code", "=", code),
                                                   ("openid", "=", openid)],
                                                  context=context)
        self.send_qy_text_ids(cr, uid, ids, content, context=context)

    def send_qy_text(self, cr, uid, code, field_name, content, context=None):
        ids = self.pool.get("rhwl.weixin").search(cr,
                                                  uid,
                                                  [("base_id.code", "=", code),
                                                   (field_name, "=", True)],
                                                  context=context)
        self.send_qy_text_ids(cr, uid, ids, content, context=context)

    def get_dept_user(self, cr, uid, id, context=None):
        obj = self.browse(cr, uid, id, context=context)
        token = self._get_token(cr,
                                SUPERUSER_ID,
                                obj.code.encode("utf-8"),
                                context=context)
        vals = {
            "access_token": token,
            "department_id": 1,
            "fetch_child": 1,
            "status": 0
        }
        s = requests.post(
            "https://qyapi.weixin.qq.com/cgi-bin/user/simplelist",
            params=vals,
            headers={'content-type': 'application/json; encoding=utf-8'},
            allow_redirects=False)
        ref = eval(s.content)
        s.close()
        if ref["errcode"] == 0:
            for i in ref["userlist"]:
                u_id = self.pool.get("rhwl.weixin").search(
                    cr, SUPERUSER_ID, [("base_id", "=", obj.id),
                                       ("openid", "=", i["userid"])])
                if not u_id:
                    self.pool.get("rhwl.weixin").create(
                        cr, SUPERUSER_ID, {
                            "base_id": obj.id,
                            "openid": i["userid"],
                            "active": True,
                            "state": "draft"
                        })
Exemplo n.º 26
0
            try:
                file_data = image_file.read()
                self._logo_image = base64.encodestring(file_data)
                return self._logo_image
            finally:
                image_file.close()
        else:
            self._logo_image = base64.encodestring(im.read())
            return self._logo_image

    def _get_image_fn(self, cr, uid, ids, name, args, context=None):
        image = self._get_image(cr, uid, context)
        return dict.fromkeys(ids, image) # ok to use .fromkeys() as the image is same for all 

    _columns = {
        'printer_ids':fields.one2many('aeroo.printers.temp', 'install_id', 'Printers'),
        'config_logo': fields.function(_get_image_fn, string='Image', type='binary', method=True),
        'state':fields.selection([
            ('init','Init'),
            ('done','Done'),
            
        ],'State', select=True, readonly=True),
    }

    def default_get(self, cr, uid, fields, context=None):
        printers_obj = self.pool.get('aeroo.printers')
        data = super(aeroo_printer_installer, self).default_get(cr, uid, fields, context=context)
        conn = cups.Connection()
        printers = conn.getPrinters()
        installed_ids = printers_obj.search(cr, 1, ['|',('active','=',False),('active','=',True)], context=context)
        printers_installed = printers_obj.read(cr, uid, installed_ids, context=context)
Exemplo n.º 27
0
class sale_order(osv.osv):
    _inherit = 'sale.order'

    def _get_total(self, cr, uid, ids, name, arg, context=None):
        res = {}
        for order in self.browse(cr, uid, ids, context=context):
            total = 0.0
            for line in order.order_line:
                total += line.price_subtotal + line.price_unit * ((line.discount or 0.0) / 100.0) * line.product_uom_qty
            res[order.id] = total
        return res

    _columns = {
        'access_token': fields.char('Security Token', required=True, copy=False),
        'template_id': fields.many2one('sale.quote.template', 'Quotation Template', readonly=True, states={'draft': [('readonly', False)], 'sent': [('readonly', False)]}),
        'website_description': fields.html('Description'),
        'options' : fields.one2many('sale.order.option', 'order_id', 'Optional Products Lines', readonly=True, states={'draft': [('readonly', False)], 'sent': [('readonly', False)]}, copy=True),
        'amount_undiscounted': fields.function(_get_total, string='Amount Before Discount', type="float", digits=0),
        'quote_viewed': fields.boolean('Quotation Viewed'),
        'require_payment': fields.selection([
            (0, 'Not mandatory on website quote validation'),
            (1, 'Immediate after website order validation')
            ], 'Payment', help="Require immediate payment by the customer when validating the order from the website quote"),
    }

    def _get_template_id(self, cr, uid, context=None):
        try:
            template_id = self.pool.get('ir.model.data').get_object_reference(cr, uid, 'website_quote', 'website_quote_template_default')[1]
        except ValueError:
            template_id = False
        return template_id

    _defaults = {
        'access_token': lambda self, cr, uid, ctx={}: str(uuid.uuid4()),
        'template_id' : _get_template_id,
    }

    def open_quotation(self, cr, uid, quote_id, context=None):
        quote = self.browse(cr, uid, quote_id[0], context=context)
        self.write(cr, uid, quote_id[0], {'quote_viewed': True}, context=context)
        return {
            'type': 'ir.actions.act_url',
            'target': 'self',
            'url': '/quote/%s/%s' % (quote.id, quote.access_token)
        }

    def onchange_template_id(self, cr, uid, ids, template_id, partner=False, fiscal_position_id=False, pricelist_id=False, context=None):
        if not template_id:
            return {}

        if partner:
            context = dict(context or {})
            context['lang'] = self.pool['res.partner'].browse(cr, uid, partner, context).lang

        pricelist_obj = self.pool['product.pricelist']

        lines = [(5,)]
        quote_template = self.pool.get('sale.quote.template').browse(cr, uid, template_id, context=context)
        for line in quote_template.quote_line:
            res = self.pool.get('sale.order.line').product_id_change(cr, uid, False,
                False, line.product_id.id, line.product_uom_qty, line.product_uom_id.id, line.product_uom_qty,
                line.product_uom_id.id, line.name, partner, False, True, time.strftime('%Y-%m-%d'),
                False, fiscal_position_id, True, context)
            data = res.get('value', {})
            if pricelist_id:
                uom_context = context.copy()
                uom_context['uom'] = line.product_uom_id.id
                price = pricelist_obj.price_get(cr, uid, [pricelist_id], line.product_id.id, 1, context=uom_context)[pricelist_id]
            else:
                price = line.price_unit

            if 'tax_id' in data:
                data['tax_id'] = [(6, 0, data['tax_id'])]
            data.update({
                'name': line.name,
                'price_unit': price,
                'discount': line.discount,
                'product_uom_qty': line.product_uom_qty,
                'product_id': line.product_id.id,
                'product_uom': line.product_uom_id.id,
                'website_description': line.website_description,
                'state': 'draft',
            })
            lines.append((0, 0, data))
        options = []
        for option in quote_template.options:
            if pricelist_id:
                uom_context = context.copy()
                uom_context['uom'] = option.uom_id.id
                price = pricelist_obj.price_get(cr, uid, [pricelist_id], option.product_id.id, 1, context=uom_context)[pricelist_id]
            else:
                price = option.price_unit
            options.append((0, 0, {
                'product_id': option.product_id.id,
                'name': option.name,
                'quantity': option.quantity,
                'uom_id': option.uom_id.id,
                'price_unit': price,
                'discount': option.discount,
                'website_description': option.website_description,
            }))
        date = False
        if quote_template.number_of_days > 0:
            date = (datetime.datetime.now() + datetime.timedelta(quote_template.number_of_days)).strftime("%Y-%m-%d")
        data = {
            'order_line': lines,
            'website_description': quote_template.website_description,
            'options': options,
            'validity_date': date,
            'require_payment': quote_template.require_payment
        }
        if quote_template.note:
            data['note'] = quote_template.note
        return {'value': data}

    def recommended_products(self, cr, uid, ids, context=None):
        order_line = self.browse(cr, uid, ids[0], context=context).order_line
        product_pool = self.pool.get('product.product')
        products = []
        for line in order_line:
            products += line.product_id.product_tmpl_id.recommended_products(context=context)
        return products

    def get_access_action(self, cr, uid, ids, context=None):
        """ Override method that generated the link to access the document. Instead
        of the classic form view, redirect to the online quote if exists. """
        quote = self.browse(cr, uid, ids[0], context=context)
        if not quote.template_id:
            return super(sale_order, self).get_access_action(cr, uid, ids, context=context)
        return {
            'type': 'ir.actions.act_url',
            'url': '/quote/%s' % quote.id,
            'target': 'self',
            'res_id': quote.id,
        }

    def action_quotation_send(self, cr, uid, ids, context=None):
        action = super(sale_order, self).action_quotation_send(cr, uid, ids, context=context)
        ir_model_data = self.pool.get('ir.model.data')
        quote_template_id = self.read(cr, uid, ids, ['template_id'], context=context)[0]['template_id']
        if quote_template_id:
            try:
                template_id = ir_model_data.get_object_reference(cr, uid, 'website_quote', 'email_template_edi_sale')[1]
            except ValueError:
                pass
            else:
                action['context'].update({
                    'default_template_id': template_id,
                    'default_use_template': True
                })

        return action

    def _confirm_online_quote(self, cr, uid, order_id, tx, context=None):
        """ Payment callback: validate the order and write tx details in chatter """
        order = self.browse(cr, uid, order_id, context=context)

        # create draft invoice if transaction is ok
        if tx and tx.state == 'done':
            if order.state in ['draft', 'sent']:
                self.signal_workflow(cr, SUPERUSER_ID, [order.id], 'manual_invoice', context=context)
            message = _('Order payed by %s. Transaction: %s. Amount: %s.') % (tx.partner_id.name, tx.acquirer_reference, tx.amount)
            self.message_post(cr, uid, order_id, body=message, type='comment', subtype='mt_comment', context=context)
            return True
        return False

    def create(self, cr, uid, values, context=None):
        if not values.get('template_id'):
            defaults = self.default_get(cr, uid, ['template_id'], context=context)
            template_values = self.onchange_template_id(cr, uid, [], defaults.get('template_id'), partner=values.get('partner_id'), fiscal_position_id=values.get('fiscal_position'), context=context).get('value', {})
            values = dict(template_values, **values)
        return super(sale_order, self).create(cr, uid, values, context=context)
Exemplo n.º 28
0
class prestashop_backend(orm.Model):
    _name = 'prestashop.backend'
    _doc = 'Prestashop Backend'
    _inherit = 'connector.backend'

    _backend_type = 'prestashop'

    def _select_versions(self, cr, uid, context=None):
        """ Available versions

        Can be inherited to add custom versions.
        """
        return [('1.5', '1.5')]

    _columns = {
        'version':
        fields.selection(_select_versions, string='Version', required=True),
        'location':
        fields.char('Location'),
        'webservice_key':
        fields.char('Webservice key',
                    help="You have to put it in 'username' of the PrestaShop "
                    "Webservice api path invite"),
        'warehouse_id':
        fields.many2one(
            'stock.warehouse',
            'Warehouse',
            required=True,
            help='Warehouse used to compute the stock quantities.'),
        'taxes_included':
        fields.boolean("Use tax included prices"),
        'import_partners_since':
        fields.datetime('Import partners since'),
        'import_orders_since':
        fields.datetime('Import Orders since'),
        'import_products_since':
        fields.datetime('Import Products since'),
        'import_refunds_since':
        fields.datetime('Import Refunds since'),
        'import_suppliers_since':
        fields.datetime('Import Suppliers since'),
        'language_ids':
        fields.one2many('prestashop.res.lang', 'backend_id', 'Languages'),
        'company_id':
        fields.many2one('res.company', 'Company', select=1, required=True),
        'discount_product_id':
        fields.many2one('product.product',
                        'Dicount Product',
                        select=1,
                        required=False),
        'shipping_product_id':
        fields.many2one('product.product',
                        'Shipping Product',
                        select=1,
                        required=False),
    }

    _defaults = {
        'company_id':
        lambda s, cr, uid, c: s.pool.get('res.company')._company_default_get(
            cr, uid, 'prestashop.backend', context=c),
    }

    def synchronize_metadata(self, cr, uid, ids, context=None):
        if not hasattr(ids, '__iter__'):
            ids = [ids]
        session = ConnectorSession(cr, uid, context=context)
        for backend_id in ids:
            for model in ('prestashop.shop.group', 'prestashop.shop'):
                # import directly, do not delay because this
                # is a fast operation, a direct return is fine
                # and it is simpler to import them sequentially
                import_batch(session, model, backend_id)
        return True

    def synchronize_basedata(self, cr, uid, ids, context=None):
        if not hasattr(ids, '__iter__'):
            ids = [ids]
        session = ConnectorSession(cr, uid, context=context)
        for backend_id in ids:
            for model_name in [
                    'prestashop.res.lang',
                    'prestashop.res.country',
                    'prestashop.res.currency',
                    'prestashop.account.tax',
            ]:
                env = get_environment(session, model_name, backend_id)
                directBinder = env.get_connector_unit(DirectBinder)
                directBinder.run()

            import_batch(session, 'prestashop.account.tax.group', backend_id)
            import_batch(session, 'prestashop.sale.order.state', backend_id)
        return True

    def _date_as_user_tz(self, cr, uid, dtstr):
        if not dtstr:
            return None
        users_obj = self.pool.get('res.users')
        user = users_obj.browse(cr, uid, uid)
        timezone = pytz.timezone(user.partner_id.tz or 'utc')
        dt = datetime.strptime(dtstr, DEFAULT_SERVER_DATETIME_FORMAT)
        dt = pytz.utc.localize(dt)
        dt = dt.astimezone(timezone)
        return dt

    def import_customers_since(self, cr, uid, ids, context=None):
        if not hasattr(ids, '__iter__'):
            ids = [ids]
        session = ConnectorSession(cr, uid, context=context)
        for backend_record in self.browse(cr, uid, ids, context=context):
            since_date = self._date_as_user_tz(
                cr, uid, backend_record.import_partners_since)
            import_customers_since.delay(
                session,
                backend_record.id,
                since_date,
                priority=10,
            )

        return True

    def import_products(self, cr, uid, ids, context=None):
        if not hasattr(ids, '__iter__'):
            ids = [ids]
        session = ConnectorSession(cr, uid, context=context)
        for backend_record in self.browse(cr, uid, ids, context=context):
            since_date = self._date_as_user_tz(
                cr, uid, backend_record.import_products_since)
            import_products.delay(session,
                                  backend_record.id,
                                  since_date,
                                  priority=10)
        return True

    def import_carriers(self, cr, uid, ids, context=None):
        if not hasattr(ids, '__iter__'):
            ids = [ids]
        session = ConnectorSession(cr, uid, context=context)
        for backend_id in ids:
            import_carriers.delay(session, backend_id, priority=10)
        return True

    def update_product_stock_qty(self, cr, uid, ids, context=None):
        if not hasattr(ids, '__iter__'):
            ids = [ids]
        session = ConnectorSession(cr, uid, context=context)
        export_product_quantities.delay(session, ids)
        return True

    def import_stock_qty(self, cr, uid, ids, context=None):
        if not hasattr(ids, '__iter__'):
            ids = [ids]
        session = ConnectorSession(cr, uid, context=context)
        for backend_id in ids:
            import_inventory.delay(session, backend_id)

    def import_sale_orders(self, cr, uid, ids, context=None):
        if not hasattr(ids, '__iter__'):
            ids = [ids]
        session = ConnectorSession(cr, uid, context=context)
        for backend_record in self.browse(cr, uid, ids, context=context):
            since_date = self._date_as_user_tz(
                cr, uid, backend_record.import_orders_since)
            import_orders_since.delay(
                session,
                backend_record.id,
                since_date,
                priority=5,
            )
        return True

    def import_payment_methods(self, cr, uid, ids, context=None):
        if not hasattr(ids, '__iter__'):
            ids = [ids]
        session = ConnectorSession(cr, uid, context=context)
        for backend_record in self.browse(cr, uid, ids, context=context):
            import_batch.delay(session, 'payment.method', backend_record.id)
        return True

    def import_refunds(self, cr, uid, ids, context=None):
        if not hasattr(ids, '__iter__'):
            ids = [ids]
        session = ConnectorSession(cr, uid, context=context)
        for backend_record in self.browse(cr, uid, ids, context=context):
            since_date = self._date_as_user_tz(
                cr, uid, backend_record.import_refunds_since)
            import_refunds.delay(session, backend_record.id, since_date)
        return True

    def import_suppliers(self, cr, uid, ids, context=None):
        if not hasattr(ids, '__iter__'):
            ids = [ids]
        session = ConnectorSession(cr, uid, context=context)
        for backend_record in self.browse(cr, uid, ids, context=context):
            since_date = self._date_as_user_tz(
                cr, uid, backend_record.import_suppliers_since)
            import_suppliers.delay(session, backend_record.id, since_date)
        return True

    def _scheduler_launch(self, cr, uid, callback, domain=None, context=None):
        if domain is None:
            domain = []
        ids = self.search(cr, uid, domain, context=context)
        if ids:
            callback(cr, uid, ids, context=context)

    def _scheduler_update_product_stock_qty(self,
                                            cr,
                                            uid,
                                            domain=None,
                                            context=None):
        self._scheduler_launch(cr,
                               uid,
                               self.update_product_stock_qty,
                               domain=domain,
                               context=context)

    def _scheduler_import_sale_orders(self,
                                      cr,
                                      uid,
                                      domain=None,
                                      context=None):
        self._scheduler_launch(cr,
                               uid,
                               self.import_sale_orders,
                               domain=domain,
                               context=context)

    def _scheduler_import_customers(self, cr, uid, domain=None, context=None):
        self._scheduler_launch(cr,
                               uid,
                               self.import_customers_since,
                               domain=domain,
                               context=context)

    def _scheduler_import_products(self, cr, uid, domain=None, context=None):
        self._scheduler_launch(cr,
                               uid,
                               self.import_products,
                               domain=domain,
                               context=context)

    def _scheduler_import_carriers(self, cr, uid, domain=None, context=None):
        self._scheduler_launch(cr,
                               uid,
                               self.import_carriers,
                               domain=domain,
                               context=context)

    def _scheduler_import_payment_methods(self,
                                          cr,
                                          uid,
                                          domain=None,
                                          context=None):
        self._scheduler_launch(cr,
                               uid,
                               self.import_payment_methods,
                               domain=domain,
                               context=context)

    def _scheduler_import_refunds(self, cr, uid, domain=None, context=None):
        self._scheduler_launch(cr,
                               uid,
                               self.import_refunds,
                               domain=domain,
                               context=context)

    def _scheduler_import_suppliers(self, cr, uid, domain=None, context=None):
        self._scheduler_launch(cr,
                               uid,
                               self.import_suppliers,
                               domain=domain,
                               context=context)

    def import_record(self,
                      cr,
                      uid,
                      backend_id,
                      model_name,
                      ext_id,
                      context=None):
        session = ConnectorSession(cr, uid, context=context)
        import_record(session, model_name, backend_id, ext_id)
        return True
Exemplo n.º 29
0
class sale_devis(osv.osv):
    _name = "sale.devis"
    _description = "Sales Devis"
    _rec_name = 'reference'
    _order = "reference desc, id desc"

    def draft(self, cr, uid, ids):
        self.write(cr, uid, ids, {'state': 'draft'})
        return True

    def envoyer(self, cr, uid, ids, context):
        '''
           Methode du workflow: changer l'état du devis à l'état envoyé
        '''
        self.reset_taxes(cr, uid, ids, context)
        self.write(cr, uid, ids, {'state': 'sent'})
        return True

    def confirmer(self, cr, uid, ids, context):
        '''
           Methode du workflow: permet la confirmation du devis et la création du Bon de commande
        '''
        self.reset_taxes(cr, uid, ids, context)
        self.write(cr, uid, ids, {'state': 'confirmed'})

        return True

    def create(self, cr, uid, vals, context=None):
        vals['reference'] = self.pool.get('ir.sequence').get(
            cr, uid, 'sale.devis')

        new_id = super(sale_devis, self).create(cr, uid, vals, context=context)
        self.reset_taxes(cr, uid, [new_id], context)
        return new_id

    def action_view_order(self, cr, uid, ids, context=None):
        for devis in self.browse(cr, uid, ids):
            mod_obj = self.pool.get('ir.model.data')
            act_obj = self.pool.get('ir.actions.act_window')

            result = mod_obj.get_object_reference(cr, uid, 'sale',
                                                  'action_order_tree')
            id = result and result[1] or False
            result = act_obj.read(cr, uid, [id], context=context)[0]
            res = mod_obj.get_object_reference(cr, uid, 'sale',
                                               'view_order_form')
            result['views'] = [(res and res[1] or False, 'form')]
            cr.execute("select id from sale_order where devis_id = %s",
                       (devis.id, ))
            res = cr.dictfetchone()
            result['res_id'] = res['id']
            return result

    def _currency_get(self, cr, uid, context=None):
        ids = self.pool.get('res.currency').search(cr,
                                                   uid, [('name', '=', 'TND')],
                                                   context=context)
        return ids[0]

    @api.one
    @api.depends('devis_lines.price_subtotal', 'tax_lines.amount')
    def _amount_all(self):
        '''
           Methode qui calcule les montants suivants
           amount_untaxed
           amount_tax
           amount_total
           undiscount_total
           discount_total  
        '''
        print "partner_id.exone===", self.partner_id.exoner
        if self.partner_id.exoner:
            self.amount_tax = 0
        else:
            self.amount_tax = sum(line.amount for line in self.tax_lines)
        self.amount_untaxed = sum(line.price_subtotal
                                  for line in self.devis_lines)

        self.discount_total = sum((line.product_qty * line.price_unit *
                                   ((line.discount or 0.0) / 100.0))
                                  for line in self.devis_lines)
        self.undiscount_total = sum(line.product_qty * line.price_unit
                                    for line in self.devis_lines)
        self.amount_total = self.amount_untaxed + self.amount_tax

    _columns = {
        'reference':
        fields.char('Référence', size=64, readonly=True),
        'date':
        fields.datetime('Date', required=True),
        'partner_id':
        fields.many2one('res.partner',
                        'Client',
                        required=True,
                        domain="[('customer','=',True)]"),
        'company_id':
        fields.many2one('res.company', 'Company'),
        'currency_id':
        fields.many2one('res.currency', 'Devise', required=True),
        'devis_lines':
        fields.one2many('sale.devis.line', 'devis_id', 'Ligne de devis'),
        'tax_lines':
        fields.one2many(
            'sale.devis.taxe',
            'devis_id',
            'Lignes Tax',
        ),
        'discount_total':
        fields.float(string='Total Remise',
                     digits_compute=dp.get_precision('Account'),
                     store=True,
                     readonly=True,
                     compute='_amount_all',
                     track_visibility='always'),
        'undiscount_total':
        fields.float(string='Total HT sans remise',
                     digits_compute=dp.get_precision('Account'),
                     store=True,
                     readonly=True,
                     compute='_amount_all',
                     track_visibility='always'),
        'amount_untaxed':
        fields.float(string='Total HT',
                     digits_compute=dp.get_precision('Account'),
                     store=True,
                     readonly=True,
                     compute='_amount_all',
                     track_visibility='always'),
        'amount_tax':
        fields.float(string='Total Taxe',
                     digits_compute=dp.get_precision('Account'),
                     store=True,
                     readonly=True,
                     compute='_amount_all',
                     track_visibility='always'),
        'amount_total':
        fields.float(string='Total',
                     digits_compute=dp.get_precision('Account'),
                     store=True,
                     readonly=True,
                     compute='_amount_all',
                     track_visibility='always'),
        'state':
        fields.selection([('draft', 'Brouillon'), ('sent', 'Envoyé'),
                          ('confirmed', 'Confirmé')]),
        #'comment' : fields.char('comment', size=64),
        'note':
        fields.text(),
    }
    _defaults = {
        'state':
        'draft',
        'company_id':
        lambda self, cr, uid, c: self.pool.get('res.company').
        _company_default_get(cr, uid, 'procurement.order', context=c),
        'currency_id':
        _currency_get,
    }

    def button_reset_taxes(self, cr, uid, ids, context=None):
        '''
           Action du bouton reset Taxes
        '''
        self.reset_taxes(cr, uid, ids, context)
        return True

    def reset_taxes(self, cr, uid, ids, context=None):
        '''
           Methode qui permet de calculer et mettre à jour les lignes de taxes
        '''
        if context is None:
            context = {}
        ctx = context.copy()
        ait_obj = self.pool.get('sale.devis.taxe')
        for id in ids:
            partner = self.browse(cr, uid, id, context=ctx).partner_id
            if partner.lang:
                cr.execute("DELETE FROM sale_devis_taxe WHERE devis_id=%s",
                           (id, ))
                ctx.update({'lang': partner.lang})
            for taxe in ait_obj.compute(cr, uid, id, context=ctx).values():
                ait_obj.create(cr, uid, taxe)
        return True
Exemplo n.º 30
0
    def _default_location(self, cr, uid, ids, context=None):
        try:
            loc_model, location_id = self.pool.get("ir.model.data").get_object_reference(
                cr, uid, "stock", "stock_location_stock"
            )
        except ValueError, e:
            return False
        return location_id or False

    _columns = {
        "location_id": fields.many2one("stock.location", "Location", required=True),
        "import_file": fields.binary("File", filters="*.xls"),
        # to consider the product current inventory or not, if yes then add the current inventory to the upload excel quantity as the quantity to do physical inventory
        "consider_inventory": fields.boolean("Consider Current Inventory", select=True),
        "all_done": fields.boolean("All Data Imported", readonly=True, select=True),
        "result_line": fields.one2many("stock.import.inventory.result", "import_id", "Importing Result", readonly=True),
    }
    _defaults = {"location_id": _default_location}

    def view_init(self, cr, uid, fields_list, context=None):
        """
         Creates view dynamically and adding fields at runtime.
         @param self: The object pointer.
         @param cr: A database cursor
         @param uid: ID of the user currently logged in
         @param context: A standard dictionary
         @return: New arch of view with new columns.
        """
        if context is None:
            context = {}
        super(stock_import_inventory, self).view_init(cr, uid, fields_list, context=context)
Exemplo n.º 31
0
class product_ebay(osv.osv):
    _inherit = "product.template"

    _columns = {
        'copies':
        fields.char(string="NoOfCopies"),
        'ebay_oem_code':
        fields.char(string="EbayOEM-obsolete"),
        'with_chip':
        fields.boolean(string="With chip"),
        'ebay_sync':
        fields.boolean(string="Sync with ebay"),
        'ebay_id':
        fields.one2many('ebay.ids', 'product_id', string="Ebay_ids"),
        'ebay_date_added':
        fields.datetime(string="Added to Ebay"),
        'ebay_price':
        fields.float(string="Ebay price"),
        'ebay_template_id':
        fields.many2one('ebay.template'),
        'ebay_item_location':
        fields.char(string="Ebay postal"),
        'ebay_payment_instruction':
        fields.text(string="Ebay payment instructions"),
        'ebay_shipping_cost':
        fields.float(string="Ebay shipping cost"),
        'ebay_additional_item_cost':
        fields.float(string="Ebay add. shipping cost"),
        'ebay_free_shipping':
        fields.boolean(string="Ebay free shipping"),
        'ebay_extra_name':
        fields.char(string="Ebay extra att name"),
        'ebay_extra_value':
        fields.char(string="Ebay extra att value"),
        'main_name_part':
        fields.char(string="Ebay main name part"),
        'name_parts':
        fields.one2many('ebay.name.parts', 'np_id'),
        'stock_limit':
        fields.integer(default=5, string="Ebay stock limit"),
        'ebay_listing_duration':
        fields.selection((('Days_7', '7 days'), ('Days_30', '30 days'),
                          ('GTC', 'Good `Till Canceled')),
                         string="Ebay listing duration"),
        'ebay_custom_desc':
        fields.text(string="Custom description"),
        'ebay_force_shipping_cost':
        fields.boolean(string="Use this shipping cost")
    }

    def export_now(self, cr, uid, ids, context=None):
        self.pool.get('ebay').export_products(cr,
                                              uid,
                                              ids,
                                              product_id=ids,
                                              context=None)

    def remove_product(self, cr, uid, ids, context=None):
        self.pool.get('ebay').remove_product(cr, uid, ids, context=None)

    def open_on_ebay(self, cr, uid, ids, context=None):
        #This opens link for product on ebay
        product = self.browse(cr, uid, ids, context=context)
        product = product[0]
        ebay_ids = [x.ebay_id for x in product.ebay_ids]
        if ebay_ids:
            for e in ebay_ids:
                url = 'http://cgi.ebay.it/ws/eBayISAPI.dll?ViewItem&item=%s' % str(
                    e)
                webbrowser.open(url, new=2, autoraise=True)

    def set_price(self, cr, uid, ids, context=None):

        for record in self.browse(cr, uid, ids, context=context):
            ebay_price = record.list_price - 0.1
            record.ebay_price = ebay_price

        return True

    def divide_name(self, cr, uid, ids, context=None):
        current_record = None
        for record in self.browse(cr, uid, ids, context=context):
            current_record = record

        desc = current_record.description

        if len(desc) <= 80:
            return True

        split = desc.split('FOR ')
        main = split[0] + 'FOR '
        rest = ''

        for x in range(1, len(split)):
            rest += split[x]

        others = rest.split(',')

        parts = []
        line = ''

        current_record.main_name_part = main

        for y in range(0, len(others)):
            if (len(line) + len(others[y])) < (80 - len(main)):
                if (len(line) > 0):
                    line += ", "
                line += others[y]
                if y == len(others) - 1:
                    parts.append(line)
            else:
                parts.append(line)
                line = ''

        for p in parts:
            if (p[0] == ' '):
                p = p.replace(p[0], '')

            pro_id = current_record.id
            self.pool.get('ebay.name.parts').create(cr, uid, {
                'np_id': pro_id,
                'name': p
            })

        return True
Exemplo n.º 32
0
        return val
    
    STATE_SELECTION = [
        ('draft', 'New'),    
        ('open', 'Accepted'),
        ('cancel', 'Refused'),
        ('close', 'Done')
    ]
            
    _name='devil.formulas'
    _description='Formula Calculation'
    _columns={
              'name': fields.char('Transaction Code',size=124),
              'date': fields.date('Transaction Date'),
              'cust_id': fields.many2one('devil.customer','Customer'),
              'formula_line': fields.one2many('devil.items.lines','formula_id','FormulaLines'),
<<<<<<< HEAD
              'total_amt_disc': fields.float('Amount Discount', required=True, ),
=======
>>>>>>> 08375b10183304dea2ebfe2187b2858b17177cbb
              'total_amount': fields.function(_amount_all, string='TotalAmount'),
              'state': fields.selection(STATE_SELECTION, 'Status', readonly=True, select=True),
    }
    _defaults = {
        'state': lambda *a: 'draft',
    }
    
    def button_dummy(self, cr, uid, ids, context=None):
        return True
    
    
class change_account_move_line_wizard(TransientModel):
    _name = 'change.account.move.line.wizard'
    _description = 'Wizard to manage move of move lines'

    def default_get(self, cr, uid, fields, context):
        res = super(change_account_move_line_wizard,
                    self).default_get(cr, uid, fields, context=context)
        account = self.pool.get('account.account').browse(cr,
                                                          uid,
                                                          context['active_id'],
                                                          context=context)
        # Get move line without partners per company
        partners = []
        sql_req = """
                SELECT company_id, count(*) as quantity
                FROM account_move_line
                WHERE partner_id is NULL
                AND account_id = %s
                group by company_id
                """ % (account.id)
        cr.execute(sql_req)
        for item in cr.fetchall():
            partners.append((0, 0, {
                'company_id': item[0],
                'move_number': item[1],
                'partner_id': False,
            }))

        res.update({
            'source_account_id': account.id,
            'source_company_id': account.company_id.id,
            'source_type': account.type,
            'source_move_number': account.move_number,
            'source_reconciled_move_number': account.reconciled_move_number,
            'source_closed_period_move_number':
            account.closed_period_move_number,
            'source_invoice_number': account.invoice_number,
            'source_voucher_line_number': account.voucher_line_number,
            'line_ids': partners,
        })
        return res

    # --- Columns
    _columns = {
        'source_account_id':
        fields.many2one('account.account',
                        'Source account',
                        domain=[('type', '=', 'view')],
                        readonly=True),
        'source_company_id':
        fields.many2one('res.company',
                        'Company of the source account',
                        readonly=True),
        'source_type':
        fields.char('Type of the source account', readonly=True),
        'source_move_number':
        fields.integer('Number of moves in the source account', readonly=True),
        'source_invoice_number':
        fields.integer('Number of invoices in the source account',
                       readonly=True),
        'source_voucher_line_number':
        fields.integer('Number of voucher line in the source account',
                       readonly=True),
        'source_reconciled_move_number':
        fields.integer('Number of reconciled moves in the source account',
                       readonly=True),
        'source_closed_period_move_number':
        fields.integer('Number of moves in closed periods', readonly=True),
        'destination_account_id':
        fields.many2one('account.account',
                        'Destination account',
                        required=True,
                        domain=[('type', '!=', 'view')]),
        'destination_company_id':
        fields.many2one('res.company',
                        'Company of the destination account',
                        readonly=True),
        'destination_type':
        fields.char('Type of the destination account', readonly=True),
        'destination_move_number':
        fields.integer('Number of moves in the destination account',
                       readonly=True),
        'change_view_type':
        fields.boolean('Change source account in view type'),
        'line_ids':
        fields.one2many('change.account.move.line.wizard.line', 'wizard_id',
                        'Partners list'),
    }

    def onchange_destination_account_id(self, cr, uid, ids,
                                        destination_account_id,
                                        destination_company_id,
                                        destination_type,
                                        destination_move_number, context):
        if destination_account_id:
            account = self.pool.get('account.account').browse(
                cr, uid, destination_account_id, context=context)
            return {
                'value': {
                    'destination_company_id': account.company_id.id,
                    'destination_type': account.type,
                    'destination_move_number': account.move_number,
                }
            }
        else:
            return {
                'value': {
                    'destination_company_id': None,
                    'destination_type': None,
                    'destination_move_number': None,
                }
            }
        return {}

    def button_change_move_line(self, cr, uid, ids, context=None):
        aa_obj = self.pool.get('account.account')
        ai_obj = self.pool.get('account.invoice')
        am_obj = self.pool.get('account.move')
        aml_obj = self.pool.get('account.move.line')
        ap_obj = self.pool.get('account.period')
        avl_obj = self.pool.get('account.voucher.line')
        reconcile_infos = {}
        close_period_infos = []
        for data in self.browse(cr, uid, ids, context=context):
            # check constraint
            if not (data.source_account_id.company_id.id !=
                    data.destination_account_id.company_id.id):
                assert 'Incorrect request', _(
                    'Source and destination account must be belong to the same company.'
                )

            # Select all account_move_line to change
            aml_ids = aml_obj.search(
                cr,
                uid, [
                    ('account_id', '=', data.source_account_id.id),
                ],
                context=context)

            # Select all account_invoice to change
            ai_ids = ai_obj.search(
                cr,
                uid, [
                    ('account_id', '=', data.source_account_id.id),
                ],
                context=context)

            # Select all account_invoice to change
            avl_ids = avl_obj.search(
                cr,
                uid, [
                    ('account_id', '=', data.source_account_id.id),
                ],
                context=context)
            print avl_ids

            if aml_ids:
                # Search reconciled move lines
                aml_reconcile_ids = aml_obj.search(
                    cr,
                    uid, [
                        ('account_id', '=', data.source_account_id.id),
                        ('reconcile_id', '!=', False),
                    ],
                    context=context)

                # Select all account_move associated to set them in draft state
                cr.execute(
                    "SELECT distinct(move_id) FROM account_move_line WHERE id in (%s)"
                    % (str(aml_ids).strip('[]'), ))
                move_ids = [r[0] for r in cr.fetchall()]

                # backup reconcile information
                for aml in aml_obj.browse(cr,
                                          uid,
                                          aml_reconcile_ids,
                                          context=context):
                    reconcile_infos[aml.id] = aml.reconcile_id.id

                # Redo reconcile
                aml_obj.write(cr,
                              uid,
                              aml_reconcile_ids, {
                                  'reconcile_id': False,
                              },
                              context=context)

                # Backup periods
                cr.execute("""
                    SELECT distinct(period_id) 
                    FROM account_move_line aml 
                    INNER JOIN account_period ap ON aml.period_id =ap.id 
                    WHERE aml.id in (%s) 
                    AND ap.state in ('done')
                    """ % (str(aml_ids).strip('[]'), ))
                close_period_infos = [r[0] for r in cr.fetchall()]

                # Open Closed periods
                if close_period_infos:
                    ap_obj.action_draft(cr, uid, close_period_infos)

                # Cancel all account_move associated
                am_obj.button_cancel(cr, uid, move_ids, context=context)

                # Change account_move_line account
                aml_obj.write(cr,
                              uid,
                              aml_ids, {
                                  'account_id': data.destination_account_id.id,
                              },
                              context=context)

                # Change account_move_line partner, if it not set
                for line_id in data.line_ids:
                    aml_partner_ids = aml_obj.search(
                        cr,
                        uid, [
                            ('id', 'in', aml_ids),
                            ('partner_id', '=', False),
                            ('company_id', '=', line_id.company_id.id),
                        ],
                        context=context)
                    aml_obj.write(cr,
                                  uid,
                                  aml_partner_ids, {
                                      'partner_id': line_id.partner_id.id,
                                  },
                                  context=context)

                # Validate again all account_move associated
                am_obj.button_validate(cr, uid, move_ids, context=context)

                # Redo reconcile
                for aml_reconcile_id in aml_reconcile_ids:
                    aml_obj.write(
                        cr,
                        uid,
                        aml_reconcile_id, {
                            'reconcile_id': reconcile_infos[aml_reconcile_id],
                        },
                        context=context)

                # Close periods
                # NOTA : A function doesn't exist to do that. (except in a transient model)
                if close_period_infos:
                    mode = 'done'
                    cr.execute(
                        'update account_journal_period set state=%s where period_id in %s',
                        (
                            mode,
                            tuple(close_period_infos),
                        ))
                    cr.execute(
                        'update account_period set state=%s where id in %s', (
                            mode,
                            tuple(close_period_infos),
                        ))

            if ai_ids:
                # change account_invoice account
                ai_obj.write(cr,
                             uid,
                             ai_ids, {
                                 'account_id': data.destination_account_id.id,
                             },
                             context=context)

            if avl_ids:
                print avl_ids
                # change account_voucher_line account
                avl_obj.write(cr,
                              uid,
                              avl_ids, {
                                  'account_id': data.destination_account_id.id,
                              },
                              context=context)

            # (Optional) change type of the source account
            if data.change_view_type:
                aa_obj.write(cr,
                             uid, [data.source_account_id.id], {
                                 'type': 'view',
                             },
                             context=context)

        return {}
Exemplo n.º 34
0
    _columns = {
        'name': fields.text('Description', required=True, readonly=True, states={'draft': [('readonly', False)]}),
        'order_id': fields.many2one('rent.order', 'Rent Reference', required=True, ondelete='cascade', select=True, readonly=True, states={'draft':[('readonly',False)]}),
        'sequence': fields.integer('Sequence'),
        'product_id': fields.many2one('product.product', 'Product', domain=[('is_rent', '=', True)], change_default=True),
        'invoice_lines': fields.many2many('account.invoice.line', 'rent_order_line_invoice_rel', 'order_line_id', 'invoice_id', 'Invoice Lines', readonly=True),
        'price_unit': fields.float('Unit Price', required=True, digits_compute= dp.get_precision('Product Price'), readonly=True, states={'draft': [('readonly', False)]}),
        'price_subtotal': fields.function(_amount_line, string='Subtotal', digits_compute= dp.get_precision('Account')),
        'tax_id': fields.many2many('account.tax', 'rent_order_tax', 'order_line_id', 'tax_id', 'Taxes', readonly=True, states={'draft': [('readonly', False)]}),
        'product_uom_qty': fields.float('Quantity', digits_compute= dp.get_precision('Product Unit of Measure'), required=True, readonly=True, states={'draft': [('readonly', False)]}),
        'product_uom': fields.many2one('product.uom', 'Unit of Measure ', required=True, readonly=True, states={'draft': [('readonly', False)]}),
        'product_uos_qty': fields.float('Quantity (UoS)' ,digits_compute= dp.get_precision('Product UoS'), readonly=True, states={'draft': [('readonly', False)]}),
        'product_uos': fields.many2one('product.uom', 'Product UoS'),
        'product_rent_qty': fields.function(_product_rent_qty, string='Rent Quantity', digits_compute= dp.get_precision('Product UoS')),
        'th_weight': fields.float('Weight', readonly=True, states={'draft': [('readonly', False)]}),
        'move_ids': fields.one2many('stock.move', 'rent_line_id', 'Inventory Moves', readonly=True),
        'state': fields.selection([
            ('draft', 'Draft'),
            ('cancel', 'Cancelled'),
            ('confirmed', 'Waiting Approval'),
            ('accepted', 'Approved'),
            ('returned', 'Returned'),
            ('done', 'Done'),
            ], 'Status', required=True, readonly=True),
        'order_partner_id': fields.related('order_id', 'partner_id', type='many2one', relation='res.partner', store=True, string='Customer'),
        'salesman_id':fields.related('order_id', 'user_id', type='many2one', relation='res.users', store=True, string='Salesperson'),
        'company_id': fields.related('order_id', 'company_id', type='many2one', relation='res.company', string='Company', store=True, readonly=True),
    }

    _order = 'order_id desc, sequence, id'
Exemplo n.º 35
0
class sale_order(osv.osv):
    _inherit = "sale.order"

    def copy(self, cr, uid, id, default=None, context=None):
        if not default:
            default = {}
        default.update({
            'shipped': False,
            'picking_ids': [],
        })
        return super(sale_order, self).copy(cr,
                                            uid,
                                            id,
                                            default,
                                            context=context)

    def shipping_policy_change(self, cr, uid, ids, policy, context=None):
        if not policy:
            return {}
        inv_qty = 'order'
        if policy == 'prepaid':
            inv_qty = 'order'
        elif policy == 'picking':
            inv_qty = 'procurement'
        return {'value': {'invoice_quantity': inv_qty}}

    def write(self, cr, uid, ids, vals, context=None):
        if vals.get('order_policy', False):
            if vals['order_policy'] == 'prepaid':
                vals.update({'invoice_quantity': 'order'})
            elif vals['order_policy'] == 'picking':
                vals.update({'invoice_quantity': 'procurement'})
        return super(sale_order, self).write(cr,
                                             uid,
                                             ids,
                                             vals,
                                             context=context)

    def create(self, cr, uid, vals, context=None):
        if vals.get('order_policy', False):
            if vals['order_policy'] == 'prepaid':
                vals.update({'invoice_quantity': 'order'})
            if vals['order_policy'] == 'picking':
                vals.update({'invoice_quantity': 'procurement'})
        order = super(sale_order, self).create(cr, uid, vals, context=context)
        return order

    # This is False
    def _picked_rate(self, cr, uid, ids, name, arg, context=None):
        if not ids:
            return {}
        res = {}
        tmp = {}
        for id in ids:
            tmp[id] = {'picked': 0.0, 'total': 0.0}
        cr.execute(
            '''SELECT
                p.sale_id as sale_order_id, sum(m.product_qty) as nbr, mp.state as procurement_state, m.state as move_state, p.type as picking_type
            FROM
                stock_move m
            LEFT JOIN
                stock_picking p on (p.id=m.picking_id)
            LEFT JOIN
                procurement_order mp on (mp.move_id=m.id)
            WHERE
                p.sale_id IN %s GROUP BY m.state, mp.state, p.sale_id, p.type''',
            (tuple(ids), ))

        for item in cr.dictfetchall():
            if item['move_state'] == 'cancel':
                continue

            if item['picking_type'] == 'in':  #this is a returned picking
                tmp[item['sale_order_id']]['total'] -= item[
                    'nbr'] or 0.0  # Deducting the return picking qty
                if item['procurement_state'] == 'done' or item[
                        'move_state'] == 'done':
                    tmp[item['sale_order_id']]['picked'] -= item['nbr'] or 0.0
            else:
                tmp[item['sale_order_id']]['total'] += item['nbr'] or 0.0
                if item['procurement_state'] == 'done' or item[
                        'move_state'] == 'done':
                    tmp[item['sale_order_id']]['picked'] += item['nbr'] or 0.0

        for order in self.browse(cr, uid, ids, context=context):
            if order.shipped:
                res[order.id] = 100.0
            else:
                res[order.id] = tmp[order.id]['total'] and (
                    100.0 * tmp[order.id]['picked'] /
                    tmp[order.id]['total']) or 0.0
        return res

    _columns = {
        'state':
        fields.selection(
            [
                ('draft', 'Draft Quotation'),
                ('sent', 'Quotation Sent'),
                ('cancel', 'Cancelled'),
                ('waiting_date', 'Waiting Schedule'),
                ('progress', 'Sales Order'),
                ('manual', 'Sale to Invoice'),
                ('shipping_except', 'Shipping Exception'),
                ('invoice_except', 'Invoice Exception'),
                ('done', 'Done'),
            ],
            'Status',
            readonly=True,
            help="Gives the status of the quotation or sales order.\
              \nThe exception status is automatically set when a cancel operation occurs \
              in the invoice validation (Invoice Exception) or in the picking list process (Shipping Exception).\nThe 'Waiting Schedule' status is set when the invoice is confirmed\
               but waiting for the scheduler to run on the order date.",
            select=True),
        'incoterm':
        fields.many2one(
            'stock.incoterms',
            'Incoterm',
            help=
            "International Commercial Terms are a series of predefined commercial terms used in international transactions."
        ),
        'picking_policy':
        fields.selection(
            [('direct', 'Deliver each product when available'),
             ('one', 'Deliver all products at once')],
            'Shipping Policy',
            required=True,
            readonly=True,
            states={
                'draft': [('readonly', False)],
                'sent': [('readonly', False)]
            },
            help=
            """Pick 'Deliver each product when available' if you allow partial delivery."""
        ),
        'order_policy':
        fields.selection(
            [
                ('manual', 'On Demand'),
                ('picking', 'On Delivery Order'),
                ('prepaid', 'Before Delivery'),
            ],
            'Create Invoice',
            required=True,
            readonly=True,
            states={
                'draft': [('readonly', False)],
                'sent': [('readonly', False)]
            },
            help=
            """On demand: A draft invoice can be created from the sales order when needed. \nOn delivery order: A draft invoice can be created from the delivery order when the products have been delivered. \nBefore delivery: A draft invoice is created from the sales order and must be paid before the products can be delivered."""
        ),
        'picking_ids':
        fields.one2many(
            'stock.picking.out',
            'sale_id',
            'Related Picking',
            readonly=True,
            help=
            "This is a list of delivery orders that has been generated for this sales order."
        ),
        'shipped':
        fields.boolean(
            'Delivered',
            readonly=True,
            help=
            "It indicates that the sales order has been delivered. This field is updated only after the scheduler(s) have been launched."
        ),
        'picked_rate':
        fields.function(_picked_rate, string='Picked', type='float'),
        'invoice_quantity':
        fields.selection(
            [('order', 'Ordered Quantities'),
             ('procurement', 'Shipped Quantities')],
            'Invoice on',
            help=
            "The sales order will automatically create the invoice proposition (draft invoice).\
                                              You have to choose  if you want your invoice based on ordered ",
            required=True,
            readonly=True,
            states={'draft': [('readonly', False)]}),
    }
    _defaults = {
        'picking_policy': 'direct',
        'order_policy': 'manual',
        'invoice_quantity': 'order',
    }

    # Form filling
    def unlink(self, cr, uid, ids, context=None):
        sale_orders = self.read(cr, uid, ids, ['state'], context=context)
        unlink_ids = []
        for s in sale_orders:
            if s['state'] in ['draft', 'cancel']:
                unlink_ids.append(s['id'])
            else:
                raise osv.except_osv(
                    _('Invalid Action!'),
                    _('In order to delete a confirmed sales order, you must cancel it.\nTo do so, you must first cancel related picking for delivery orders.'
                      ))

        return osv.osv.unlink(self, cr, uid, unlink_ids, context=context)

    def action_view_delivery(self, cr, uid, ids, context=None):
        '''
        This function returns an action that display existing delivery orders of given sales order ids. It can either be a in a list or in a form view, if there is only one delivery order to show.
        '''
        mod_obj = self.pool.get('ir.model.data')
        act_obj = self.pool.get('ir.actions.act_window')

        result = mod_obj.get_object_reference(cr, uid, 'stock',
                                              'action_picking_tree')
        id = result and result[1] or False
        result = act_obj.read(cr, uid, [id], context=context)[0]
        #compute the number of delivery orders to display
        pick_ids = []
        for so in self.browse(cr, uid, ids, context=context):
            pick_ids += [picking.id for picking in so.picking_ids]
        #choose the view_mode accordingly
        if len(pick_ids) > 1:
            result['domain'] = "[('id','in',[" + ','.join(map(
                str, pick_ids)) + "])]"
        else:
            res = mod_obj.get_object_reference(cr, uid, 'stock',
                                               'view_picking_out_form')
            result['views'] = [(res and res[1] or False, 'form')]
            result['res_id'] = pick_ids and pick_ids[0] or False
        return result

    def action_invoice_create(self,
                              cr,
                              uid,
                              ids,
                              grouped=False,
                              states=['confirmed', 'done', 'exception'],
                              date_invoice=False,
                              context=None):
        picking_obj = self.pool.get('stock.picking')
        res = super(sale_order,
                    self).action_invoice_create(cr,
                                                uid,
                                                ids,
                                                grouped=grouped,
                                                states=states,
                                                date_invoice=date_invoice,
                                                context=context)
        for order in self.browse(cr, uid, ids, context=context):
            if order.order_policy == 'picking':
                picking_obj.write(cr, uid,
                                  map(lambda x: x.id, order.picking_ids),
                                  {'invoice_state': 'invoiced'})
        return res

    def action_cancel(self, cr, uid, ids, context=None):
        wf_service = netsvc.LocalService("workflow")
        if context is None:
            context = {}
        sale_order_line_obj = self.pool.get('sale.order.line')
        proc_obj = self.pool.get('procurement.order')
        for sale in self.browse(cr, uid, ids, context=context):
            for pick in sale.picking_ids:
                if pick.state not in ('draft', 'cancel'):
                    raise osv.except_osv(
                        _('Cannot cancel sales order!'),
                        _('You must first cancel all delivery order(s) attached to this sales order.'
                          ))
                if pick.state == 'cancel':
                    for mov in pick.move_lines:
                        proc_ids = proc_obj.search(cr, uid,
                                                   [('move_id', '=', mov.id)])
                        if proc_ids:
                            for proc in proc_ids:
                                wf_service.trg_validate(
                                    uid, 'procurement.order', proc,
                                    'button_check', cr)
            for r in self.read(cr, uid, ids, ['picking_ids']):
                for pick in r['picking_ids']:
                    wf_service.trg_validate(uid, 'stock.picking', pick,
                                            'button_cancel', cr)
        return super(sale_order, self).action_cancel(cr,
                                                     uid,
                                                     ids,
                                                     context=context)

    def action_wait(self, cr, uid, ids, context=None):
        res = super(sale_order, self).action_wait(cr,
                                                  uid,
                                                  ids,
                                                  context=context)
        for o in self.browse(cr, uid, ids):
            noprod = self.test_no_product(cr, uid, o, context)
            if noprod and o.order_policy == 'picking':
                self.write(cr,
                           uid, [o.id], {'order_policy': 'manual'},
                           context=context)
        return res

    def procurement_lines_get(self, cr, uid, ids, *args):
        res = []
        for order in self.browse(cr, uid, ids, context={}):
            for line in order.order_line:
                if line.procurement_id:
                    res.append(line.procurement_id.id)
        return res

    def date_to_datetime(self, cr, uid, userdate, context=None):
        """ Convert date values expressed in user's timezone to
        server-side UTC timestamp, assuming a default arbitrary
        time of 12:00 AM - because a time is needed.
    
        :param str userdate: date string in in user time zone
        :return: UTC datetime string for server-side use
        """
        # TODO: move to fields.datetime in server after 7.0
        user_date = datetime.strptime(userdate, DEFAULT_SERVER_DATE_FORMAT)
        if context and context.get('tz'):
            tz_name = context['tz']
        else:
            tz_name = self.pool.get('res.users').read(cr, SUPERUSER_ID, uid,
                                                      ['tz'])['tz']
        if tz_name:
            utc = pytz.timezone('UTC')
            context_tz = pytz.timezone(tz_name)
            user_datetime = user_date + relativedelta(hours=12.0)
            local_timestamp = context_tz.localize(user_datetime, is_dst=False)
            user_datetime = local_timestamp.astimezone(utc)
            return user_datetime.strftime(DEFAULT_SERVER_DATETIME_FORMAT)
        return user_date.strftime(DEFAULT_SERVER_DATETIME_FORMAT)

    # if mode == 'finished':
    #   returns True if all lines are done, False otherwise
    # if mode == 'canceled':
    #   returns True if there is at least one canceled line, False otherwise
    def test_state(self, cr, uid, ids, mode, *args):
        assert mode in ('finished',
                        'canceled'), _("invalid mode for test_state")
        finished = True
        canceled = False
        write_done_ids = []
        write_cancel_ids = []
        for order in self.browse(cr, uid, ids, context={}):
            for line in order.order_line:
                if (not line.procurement_id) or (line.procurement_id.state
                                                 == 'done'):
                    if line.state != 'done':
                        write_done_ids.append(line.id)
                else:
                    finished = False
                if line.procurement_id:
                    if (line.procurement_id.state == 'cancel'):
                        canceled = True
                        if line.state != 'exception':
                            write_cancel_ids.append(line.id)
        if write_done_ids:
            self.pool.get('sale.order.line').write(cr, uid, write_done_ids,
                                                   {'state': 'done'})
        if write_cancel_ids:
            self.pool.get('sale.order.line').write(cr, uid, write_cancel_ids,
                                                   {'state': 'exception'})

        if mode == 'finished':
            return finished
        elif mode == 'canceled':
            return canceled

    def _prepare_order_line_procurement(self,
                                        cr,
                                        uid,
                                        order,
                                        line,
                                        move_id,
                                        date_planned,
                                        context=None):
        return {
            'name': line.name,
            'origin': order.name,
            'date_planned': date_planned,
            'product_id': line.product_id.id,
            'product_qty': line.product_uom_qty,
            'product_uom': line.product_uom.id,
            'product_uos_qty': (line.product_uos and line.product_uos_qty)\
                    or line.product_uom_qty,
            'product_uos': (line.product_uos and line.product_uos.id)\
                    or line.product_uom.id,
            'location_id': order.shop_id.warehouse_id.lot_stock_id.id,
            'procure_method': line.product_id.procure_method,
            'move_id': move_id,
            'company_id': order.company_id.id,
            'note': line.name,
        }

    def _prepare_order_line_move(self,
                                 cr,
                                 uid,
                                 order,
                                 line,
                                 picking_id,
                                 date_planned,
                                 context=None):
        location_id = order.shop_id.warehouse_id.lot_stock_id.id
        output_id = order.shop_id.warehouse_id.lot_output_id.id
        return {
            'name': line.name,
            'picking_id': picking_id,
            'product_id': line.product_id.id,
            'date': date_planned,
            'date_expected': date_planned,
            'product_qty': line.product_uom_qty,
            'product_uom': line.product_uom.id,
            'product_uos_qty': (line.product_uos and line.product_uos_qty) or line.product_uom_qty,
            'product_uos': (line.product_uos and line.product_uos.id)\
                    or line.product_uom.id,
            'product_packaging': line.product_packaging.id,
            'partner_id': line.address_allotment_id.id or order.partner_shipping_id.id,
            'location_id': location_id,
            'location_dest_id': output_id,
            'sale_line_id': line.id,
            'tracking_id': False,
            'state': 'draft',
            #'state': 'waiting',
            'company_id': order.company_id.id,
            'price_unit': line.product_id.standard_price or 0.0
        }

    def _prepare_order_picking(self, cr, uid, order, context=None):
        pick_name = self.pool.get('ir.sequence').get(cr, uid,
                                                     'stock.picking.out')
        return {
            'name': pick_name,
            'origin': order.name,
            'date': self.date_to_datetime(cr, uid, order.date_order, context),
            'type': 'out',
            'state': 'auto',
            'move_type': order.picking_policy,
            'sale_id': order.id,
            'partner_id': order.partner_shipping_id.id,
            'note': order.note,
            'invoice_state': (order.order_policy == 'picking' and '2binvoiced')
            or 'none',
            'company_id': order.company_id.id,
        }

    def ship_recreate(self, cr, uid, order, line, move_id, proc_id):
        # FIXME: deals with potentially cancelled shipments, seems broken (specially if shipment has production lot)
        """
        Define ship_recreate for process after shipping exception
        param order: sales order to which the order lines belong
        param line: sales order line records to procure
        param move_id: the ID of stock move
        param proc_id: the ID of procurement
        """
        move_obj = self.pool.get('stock.move')
        if order.state == 'shipping_except':
            for pick in order.picking_ids:
                for move in pick.move_lines:
                    if move.state == 'cancel':
                        mov_ids = move_obj.search(
                            cr, uid, [('state', '=', 'cancel'),
                                      ('sale_line_id', '=', line.id),
                                      ('picking_id', '=', pick.id)])
                        if mov_ids:
                            for mov in move_obj.browse(cr, uid, mov_ids):
                                # FIXME: the following seems broken: what if move_id doesn't exist? What if there are several mov_ids? Shouldn't that be a sum?
                                move_obj.write(
                                    cr, uid, [move_id], {
                                        'product_qty': mov.product_qty,
                                        'product_uos_qty': mov.product_uos_qty
                                    })
                                self.pool.get('procurement.order').write(
                                    cr, uid, [proc_id], {
                                        'product_qty': mov.product_qty,
                                        'product_uos_qty': mov.product_uos_qty
                                    })
        return True

    def _get_date_planned(self,
                          cr,
                          uid,
                          order,
                          line,
                          start_date,
                          context=None):
        start_date = self.date_to_datetime(cr, uid, start_date, context)
        date_planned = datetime.strptime(
            start_date, DEFAULT_SERVER_DATETIME_FORMAT) + relativedelta(
                days=line.delay or 0.0)
        date_planned = (date_planned -
                        timedelta(days=order.company_id.security_lead)
                        ).strftime(DEFAULT_SERVER_DATETIME_FORMAT)
        return date_planned

    def _create_pickings_and_procurements(self,
                                          cr,
                                          uid,
                                          order,
                                          order_lines,
                                          picking_id=False,
                                          context=None):
        """Create the required procurements to supply sales order lines, also connecting
        the procurements to appropriate stock moves in order to bring the goods to the
        sales order's requested location.

        If ``picking_id`` is provided, the stock moves will be added to it, otherwise
        a standard outgoing picking will be created to wrap the stock moves, as returned
        by :meth:`~._prepare_order_picking`.

        Modules that wish to customize the procurements or partition the stock moves over
        multiple stock pickings may override this method and call ``super()`` with
        different subsets of ``order_lines`` and/or preset ``picking_id`` values.

        :param browse_record order: sales order to which the order lines belong
        :param list(browse_record) order_lines: sales order line records to procure
        :param int picking_id: optional ID of a stock picking to which the created stock moves
                               will be added. A new picking will be created if ommitted.
        :return: True
        """
        move_obj = self.pool.get('stock.move')
        picking_obj = self.pool.get('stock.picking')
        procurement_obj = self.pool.get('procurement.order')
        proc_ids = []

        for line in order_lines:
            if line.state == 'done':
                continue

            date_planned = self._get_date_planned(cr,
                                                  uid,
                                                  order,
                                                  line,
                                                  order.date_order,
                                                  context=context)

            if line.product_id:
                if line.product_id.type in ('product', 'consu'):
                    if not picking_id:
                        picking_id = picking_obj.create(
                            cr, uid,
                            self._prepare_order_picking(cr,
                                                        uid,
                                                        order,
                                                        context=context))
                    move_id = move_obj.create(
                        cr, uid,
                        self._prepare_order_line_move(cr,
                                                      uid,
                                                      order,
                                                      line,
                                                      picking_id,
                                                      date_planned,
                                                      context=context))
                else:
                    # a service has no stock move
                    move_id = False

                proc_id = procurement_obj.create(
                    cr, uid,
                    self._prepare_order_line_procurement(cr,
                                                         uid,
                                                         order,
                                                         line,
                                                         move_id,
                                                         date_planned,
                                                         context=context))
                proc_ids.append(proc_id)
                line.write({'procurement_id': proc_id})
                self.ship_recreate(cr, uid, order, line, move_id, proc_id)

        wf_service = netsvc.LocalService("workflow")
        if picking_id:
            wf_service.trg_validate(uid, 'stock.picking', picking_id,
                                    'button_confirm', cr)
        for proc_id in proc_ids:
            wf_service.trg_validate(uid, 'procurement.order', proc_id,
                                    'button_confirm', cr)

        val = {}
        if order.state == 'shipping_except':
            val['state'] = 'progress'
            val['shipped'] = False

            if (order.order_policy == 'manual'):
                for line in order.order_line:
                    if (not line.invoiced) and (line.state
                                                not in ('cancel', 'draft')):
                        val['state'] = 'manual'
                        break
        order.write(val)
        return True

    def action_ship_create(self, cr, uid, ids, context=None):
        for order in self.browse(cr, uid, ids, context=context):
            self._create_pickings_and_procurements(cr,
                                                   uid,
                                                   order,
                                                   order.order_line,
                                                   None,
                                                   context=context)
        return True

    def action_ship_end(self, cr, uid, ids, context=None):
        for order in self.browse(cr, uid, ids, context=context):
            val = {'shipped': True}
            if order.state == 'shipping_except':
                val['state'] = 'progress'
                if (order.order_policy == 'manual'):
                    for line in order.order_line:
                        if (not line.invoiced) and (line.state
                                                    not in ('cancel',
                                                            'draft')):
                            val['state'] = 'manual'
                            break
            for line in order.order_line:
                towrite = []
                if line.state == 'exception':
                    towrite.append(line.id)
                if towrite:
                    self.pool.get('sale.order.line').write(cr,
                                                           uid,
                                                           towrite,
                                                           {'state': 'done'},
                                                           context=context)
            res = self.write(cr, uid, [order.id], val)
        return True

    def has_stockable_products(self, cr, uid, ids, *args):
        for order in self.browse(cr, uid, ids):
            for order_line in order.order_line:
                if order_line.product_id and order_line.product_id.type in (
                        'product', 'consu'):
                    return True
        return False
Exemplo n.º 36
0
     else:
         kip_ids=",".join(map(str,ids))
         cr.execute("Select payment_import_id id from kderp_import_payment_line where payment_import_id in (%s) and state='draft'" % (kip_ids))
         list_error=[]
         for new_id in cr.fetchall():
             list_error.append(new_id[0])
         for id in ids:
             if id not in list_error:
                 self.write(cr, uid, [id], {'state':'done'})
     return True        
 
 _columns={
             'date':fields.date('Date', required=True, states={'done':[('readonly',True)]}, help="Date of Accounting Import Payment to Supplier to ERP"),
             'name':fields.char('Code Import',size=32,required=True,select=True,states={'done':[('readonly',True)]}),
             'description':fields.char('Desc.',size=128,states={'done':[('readonly',True)]}),
             'import_line':fields.one2many('kderp.import.payment.line','payment_import_id','Details',states={'done':[('readonly',True)]}),
             'state':fields.selection([('draft','Draft'),('done','Done')],'State',readonly=True,select=True)               
           }
 _sql_constraints = [
                     ('supplier_payment_import_unique',"unique(name)","KDERP Error: The Code Import must be unique !")
                     ]
 _defaults = {
     'state': 'draft',
     'date': lambda *a: time.strftime('%Y-%m-%d'),
     'name':lambda *a: time.strftime('AISP-%Y%b%d.%H%M')
     }
 
 def load(self, cr, uid, fields, data, context=None):
 #def import_data(self, cr, uid, fields, datas, mode='init', current_module='', noupdate=False, context=None, filename=None):
     try:
         payment_id_pos = fields.index('import_line/payment_number')
Exemplo n.º 37
0
class sale_order_line(osv.osv):
    def _number_packages(self, cr, uid, ids, field_name, arg, context=None):
        res = {}
        for line in self.browse(cr, uid, ids, context=context):
            try:
                res[line.id] = int(
                    (line.product_uom_qty + line.product_packaging.qty -
                     0.0001) / line.product_packaging.qty)
            except:
                res[line.id] = 1
        return res

    _inherit = 'sale.order.line'
    _columns = {
        'delay':
        fields.float(
            'Delivery Lead Time',
            required=True,
            help=
            "Number of days between the order confirmation and the shipping of the products to the customer",
            readonly=True,
            states={'draft': [('readonly', False)]}),
        'procurement_id':
        fields.many2one('procurement.order', 'Procurement'),
        'property_ids':
        fields.many2many('mrp.property',
                         'sale_order_line_property_rel',
                         'order_id',
                         'property_id',
                         'Properties',
                         readonly=True,
                         states={'draft': [('readonly', False)]}),
        'product_packaging':
        fields.many2one('product.packaging', 'Packaging'),
        'move_ids':
        fields.one2many('stock.move',
                        'sale_line_id',
                        'Inventory Moves',
                        readonly=True),
        'number_packages':
        fields.function(_number_packages,
                        type='integer',
                        string='Number Packages'),
    }
    _defaults = {
        'delay': 0.0,
        'product_packaging': False,
    }

    def _get_line_qty(self, cr, uid, line, context=None):
        if line.procurement_id and not (line.order_id.invoice_quantity
                                        == 'order'):
            return self.pool.get('procurement.order').quantity_get(
                cr, uid, line.procurement_id.id, context=context)
        else:
            return super(sale_order_line, self)._get_line_qty(cr,
                                                              uid,
                                                              line,
                                                              context=context)

    def _get_line_uom(self, cr, uid, line, context=None):
        if line.procurement_id and not (line.order_id.invoice_quantity
                                        == 'order'):
            return self.pool.get('procurement.order').uom_get(
                cr, uid, line.procurement_id.id, context=context)
        else:
            return super(sale_order_line, self)._get_line_uom(cr,
                                                              uid,
                                                              line,
                                                              context=context)

    def button_cancel(self, cr, uid, ids, context=None):
        res = super(sale_order_line, self).button_cancel(cr,
                                                         uid,
                                                         ids,
                                                         context=context)
        for line in self.browse(cr, uid, ids, context=context):
            for move_line in line.move_ids:
                if move_line.state != 'cancel':
                    raise osv.except_osv(
                        _('Cannot cancel sales order line!'),
                        _('You must first cancel stock moves attached to this sales order line.'
                          ))
        return res

    def copy_data(self, cr, uid, id, default=None, context=None):
        if not default:
            default = {}
        default.update({'move_ids': []})
        return super(sale_order_line, self).copy_data(cr,
                                                      uid,
                                                      id,
                                                      default,
                                                      context=context)

    def product_packaging_change(self,
                                 cr,
                                 uid,
                                 ids,
                                 pricelist,
                                 product,
                                 qty=0,
                                 uom=False,
                                 partner_id=False,
                                 packaging=False,
                                 flag=False,
                                 context=None):
        if not product:
            return {'value': {'product_packaging': False}}
        product_obj = self.pool.get('product.product')
        product_uom_obj = self.pool.get('product.uom')
        pack_obj = self.pool.get('product.packaging')
        warning = {}
        result = {}
        warning_msgs = ''
        if flag:
            res = self.product_id_change(cr,
                                         uid,
                                         ids,
                                         pricelist=pricelist,
                                         product=product,
                                         qty=qty,
                                         uom=uom,
                                         partner_id=partner_id,
                                         packaging=packaging,
                                         flag=False,
                                         context=context)
            warning_msgs = res.get('warning') and res['warning']['message']

        products = product_obj.browse(cr, uid, product, context=context)
        if not products.packaging:
            packaging = result['product_packaging'] = False
        elif not packaging and products.packaging and not flag:
            packaging = products.packaging[0].id
            result['product_packaging'] = packaging

        if packaging:
            default_uom = products.uom_id and products.uom_id.id
            pack = pack_obj.browse(cr, uid, packaging, context=context)
            q = product_uom_obj._compute_qty(cr, uid, uom, pack.qty,
                                             default_uom)
            #            qty = qty - qty % q + q
            if qty and (q and not (qty % q) == 0):
                ean = pack.ean or _('(n/a)')
                qty_pack = pack.qty
                type_ul = pack.ul
                if not warning_msgs:
                    warn_msg = _("You selected a quantity of %d Units.\n"
                                "But it's not compatible with the selected packaging.\n"
                                "Here is a proposition of quantities according to the packaging:\n"
                                "EAN: %s Quantity: %s Type of ul: %s") % \
                                    (qty, ean, qty_pack, type_ul.name)
                    warning_msgs += _(
                        "Picking Information ! : ") + warn_msg + "\n\n"
                warning = {
                    'title': _('Configuration Error!'),
                    'message': warning_msgs
                }
            result['product_uom_qty'] = qty

        return {'value': result, 'warning': warning}

    def product_id_change(self,
                          cr,
                          uid,
                          ids,
                          pricelist,
                          product,
                          qty=0,
                          uom=False,
                          qty_uos=0,
                          uos=False,
                          name='',
                          partner_id=False,
                          lang=False,
                          update_tax=True,
                          date_order=False,
                          packaging=False,
                          fiscal_position=False,
                          flag=False,
                          context=None):
        context = context or {}
        product_uom_obj = self.pool.get('product.uom')
        partner_obj = self.pool.get('res.partner')
        product_obj = self.pool.get('product.product')
        warning = {}
        res = super(sale_order_line,
                    self).product_id_change(cr,
                                            uid,
                                            ids,
                                            pricelist,
                                            product,
                                            qty=qty,
                                            uom=uom,
                                            qty_uos=qty_uos,
                                            uos=uos,
                                            name=name,
                                            partner_id=partner_id,
                                            lang=lang,
                                            update_tax=update_tax,
                                            date_order=date_order,
                                            packaging=packaging,
                                            fiscal_position=fiscal_position,
                                            flag=flag,
                                            context=context)

        if not product:
            res['value'].update({'product_packaging': False})
            return res

        #update of result obtained in super function
        product_obj = product_obj.browse(cr, uid, product, context=context)
        res['value']['delay'] = (product_obj.sale_delay or 0.0)
        res['value']['type'] = product_obj.procure_method

        #check if product is available, and if not: raise an error
        uom2 = False
        if uom:
            uom2 = product_uom_obj.browse(cr, uid, uom)
            if product_obj.uom_id.category_id.id != uom2.category_id.id:
                uom = False
        if not uom2:
            uom2 = product_obj.uom_id

        # Calling product_packaging_change function after updating UoM
        res_packing = self.product_packaging_change(cr,
                                                    uid,
                                                    ids,
                                                    pricelist,
                                                    product,
                                                    qty,
                                                    uom,
                                                    partner_id,
                                                    packaging,
                                                    context=context)
        res['value'].update(res_packing.get('value', {}))
        warning_msgs = res_packing.get(
            'warning') and res_packing['warning']['message'] or ''
        compare_qty = float_compare(
            product_obj.virtual_available * uom2.factor,
            qty * product_obj.uom_id.factor,
            precision_rounding=product_obj.uom_id.rounding)
        if (product_obj.type=='product') and int(compare_qty) == -1 \
          and (product_obj.procure_method=='make_to_stock'):
            warn_msg = _('You plan to sell %.2f %s but you only have %.2f %s available !\nThe real stock is %.2f %s. (without reservations)') % \
                    (qty, uom2 and uom2.name or product_obj.uom_id.name,
                     max(0,product_obj.virtual_available), product_obj.uom_id.name,
                     max(0,product_obj.qty_available), product_obj.uom_id.name)
            warning_msgs += _("Not enough stock ! : ") + warn_msg + "\n\n"

        #update of warning messages
        if warning_msgs:
            warning = {
                'title': _('Configuration Error!'),
                'message': warning_msgs
            }
        res.update({'warning': warning})
        return res
        'l10n_br_account.fiscal.category', 'Categoria'),
    'fiscal_type': fields.selection(COMPANY_FISCAL_TYPE,
        u'Regime Tributário', required=True),
    'revenue_start': fields.float(
        'Faturamento Inicial', digits_compute=dp.get_precision('Account'),
        help="Faixa inicial de faturamento bruto"),
    'revenue_end': fields.float(
        'Faturamento Final', digits_compute=dp.get_precision('Account'),
        help="Faixa inicial de faturamento bruto")
}

OTHERS_FISCAL_RULE_COLUMNS_TEMPLATE = {
    'parent_id': fields.many2one(
            'account.fiscal.position.rule.template', 'Regra Pai'),
    'child_ids': fields.one2many(
            'account.fiscal.position.rule.template',
            'parent_id', 'Regras Filhas'),
}

OTHERS_FISCAL_RULE_COLUMNS = {
    'parent_id': fields.many2one(
            'account.fiscal.position.rule', 'Regra Pai'),
    'child_ids': fields.one2many(
            'account.fiscal.position.rule', 'parent_id', 'Regras Filhas'),
}

FISCAL_RULE_DEFAULTS = {
    'fiscal_type': COMPANY_FISCAL_TYPE_DEFAULT,
    'revenue_start': 0.00,
    'revenue_end': 0.00
}
Exemplo n.º 39
0
class account_asset_asset(osv.osv):
    _name = 'account.asset.asset'
    _description = 'Asset'

    def unlink(self, cr, uid, ids, context=None):
        for asset in self.browse(cr, uid, ids, context=context):
            if asset.account_move_line_ids:
                raise osv.except_osv(
                    _('Error!'),
                    _('You cannot delete an asset that contains posted depreciation lines.'
                      ))
        return super(account_asset_asset, self).unlink(cr,
                                                       uid,
                                                       ids,
                                                       context=context)

    def _get_period(self, cr, uid, context=None):
        periods = self.pool.get('account.period').find(cr,
                                                       uid,
                                                       context=context)
        if periods:
            return periods[0]
        else:
            return False

    def _get_last_depreciation_date(self, cr, uid, ids, context=None):
        """
        @param id: ids of a account.asset.asset objects
        @return: Returns a dictionary of the effective dates of the last depreciation entry made for given asset ids. If there isn't any, return the purchase date of this asset
        """
        cr.execute(
            """
            SELECT a.id as id, COALESCE(MAX(l.date),a.purchase_date) AS date
            FROM account_asset_asset a
            LEFT JOIN account_move_line l ON (l.asset_id = a.id)
            WHERE a.id IN %s
            GROUP BY a.id, a.purchase_date """, (tuple(ids), ))
        return dict(cr.fetchall())

    def _compute_board_amount(self,
                              cr,
                              uid,
                              asset,
                              i,
                              residual_amount,
                              amount_to_depr,
                              undone_dotation_number,
                              posted_depreciation_line_ids,
                              total_days,
                              depreciation_date,
                              context=None):
        #by default amount = 0
        amount = 0
        if i == undone_dotation_number:
            amount = residual_amount
        else:
            if asset.method == 'linear':
                amount = amount_to_depr / (undone_dotation_number -
                                           len(posted_depreciation_line_ids))
                if asset.prorata:
                    amount = amount_to_depr / asset.method_number
                    days = total_days - float(depreciation_date.strftime('%j'))
                    if i == 1:
                        amount = (amount_to_depr /
                                  asset.method_number) / total_days * days
                    elif i == undone_dotation_number:
                        amount = (amount_to_depr / asset.method_number
                                  ) / total_days * (total_days - days)
            elif asset.method == 'degressive':
                amount = residual_amount * asset.method_progress_factor
                if asset.prorata:
                    days = total_days - float(depreciation_date.strftime('%j'))
                    if i == 1:
                        amount = (
                            residual_amount *
                            asset.method_progress_factor) / total_days * days
                    elif i == undone_dotation_number:
                        amount = (residual_amount *
                                  asset.method_progress_factor
                                  ) / total_days * (total_days - days)
        return amount

    def _compute_board_undone_dotation_nb(self,
                                          cr,
                                          uid,
                                          asset,
                                          depreciation_date,
                                          total_days,
                                          context=None):
        undone_dotation_number = asset.method_number
        if asset.method_time == 'end':
            end_date = datetime.strptime(asset.method_end, '%Y-%m-%d')
            undone_dotation_number = 0
            while depreciation_date <= end_date:
                depreciation_date = (
                    datetime(depreciation_date.year, depreciation_date.month,
                             depreciation_date.day) +
                    relativedelta(months=+asset.method_period))
                undone_dotation_number += 1
        if asset.prorata:
            undone_dotation_number += 1
        return undone_dotation_number

    def compute_depreciation_board(self, cr, uid, ids, context=None):
        depreciation_lin_obj = self.pool.get('account.asset.depreciation.line')
        currency_obj = self.pool.get('res.currency')
        for asset in self.browse(cr, uid, ids, context=context):
            if asset.value_residual == 0.0:
                continue
            posted_depreciation_line_ids = depreciation_lin_obj.search(
                cr,
                uid, [('asset_id', '=', asset.id), ('move_check', '=', True)],
                order='depreciation_date desc')
            old_depreciation_line_ids = depreciation_lin_obj.search(
                cr, uid, [('asset_id', '=', asset.id),
                          ('move_id', '=', False)])
            if old_depreciation_line_ids:
                depreciation_lin_obj.unlink(cr,
                                            uid,
                                            old_depreciation_line_ids,
                                            context=context)

            amount_to_depr = residual_amount = asset.value_residual
            if asset.prorata:
                depreciation_date = datetime.strptime(
                    self._get_last_depreciation_date(cr, uid, [asset.id],
                                                     context)[asset.id],
                    '%Y-%m-%d')
            else:
                # depreciation_date = 1st January of purchase year
                purchase_date = datetime.strptime(asset.purchase_date,
                                                  '%Y-%m-%d')
                #if we already have some previous validated entries, starting date isn't 1st January but last entry + method period
                if (len(posted_depreciation_line_ids) > 0):
                    last_depreciation_date = datetime.strptime(
                        depreciation_lin_obj.browse(
                            cr,
                            uid,
                            posted_depreciation_line_ids[0],
                            context=context).depreciation_date, '%Y-%m-%d')
                    depreciation_date = (
                        last_depreciation_date +
                        relativedelta(months=+asset.method_period))
                else:
                    depreciation_date = datetime(purchase_date.year, 1, 1)
            day = depreciation_date.day
            month = depreciation_date.month
            year = depreciation_date.year
            total_days = (year % 4) and 365 or 366

            undone_dotation_number = self._compute_board_undone_dotation_nb(
                cr, uid, asset, depreciation_date, total_days, context=context)
            for x in range(len(posted_depreciation_line_ids),
                           undone_dotation_number):
                i = x + 1
                amount = self._compute_board_amount(
                    cr,
                    uid,
                    asset,
                    i,
                    residual_amount,
                    amount_to_depr,
                    undone_dotation_number,
                    posted_depreciation_line_ids,
                    total_days,
                    depreciation_date,
                    context=context)
                company_currency = asset.company_id.currency_id.id
                current_currency = asset.currency_id.id
                # compute amount into company currency
                amount = currency_obj.compute(cr,
                                              uid,
                                              current_currency,
                                              company_currency,
                                              amount,
                                              context=context)
                residual_amount -= amount
                vals = {
                    'amount':
                    amount,
                    'asset_id':
                    asset.id,
                    'sequence':
                    i,
                    'name':
                    str(asset.id) + '/' + str(i),
                    'remaining_value':
                    residual_amount,
                    'depreciated_value':
                    (asset.purchase_value - asset.salvage_value) -
                    (residual_amount + amount),
                    'depreciation_date':
                    depreciation_date.strftime('%Y-%m-%d'),
                }
                depreciation_lin_obj.create(cr, uid, vals, context=context)
                # Considering Depr. Period as months
                depreciation_date = (
                    datetime(year, month, day) +
                    relativedelta(months=+asset.method_period))
                day = depreciation_date.day
                month = depreciation_date.month
                year = depreciation_date.year
        return True

    def validate(self, cr, uid, ids, context=None):
        if context is None:
            context = {}
        return self.write(cr, uid, ids, {'state': 'open'}, context)

    def set_to_close(self, cr, uid, ids, context=None):
        return self.write(cr, uid, ids, {'state': 'close'}, context=context)

    def set_to_draft(self, cr, uid, ids, context=None):
        return self.write(cr, uid, ids, {'state': 'draft'}, context=context)

    def _amount_residual(self, cr, uid, ids, name, args, context=None):
        cr.execute(
            """SELECT
                l.asset_id as id, SUM(abs(l.debit-l.credit)) AS amount
            FROM
                account_move_line l
            WHERE
                l.asset_id IN %s GROUP BY l.asset_id """, (tuple(ids), ))
        res = dict(cr.fetchall())
        for asset in self.browse(cr, uid, ids, context):
            res[asset.id] = asset.purchase_value - res.get(
                asset.id, 0.0) - asset.salvage_value
        for id in ids:
            res.setdefault(id, 0.0)
        return res

    def onchange_company_id(self,
                            cr,
                            uid,
                            ids,
                            company_id=False,
                            context=None):
        val = {}
        if company_id:
            company = self.pool.get('res.company').browse(cr,
                                                          uid,
                                                          company_id,
                                                          context=context)
            if company.currency_id.company_id and company.currency_id.company_id.id != company_id:
                val['currency_id'] = False
            else:
                val['currency_id'] = company.currency_id.id
        return {'value': val}

    def onchange_purchase_salvage_value(self,
                                        cr,
                                        uid,
                                        ids,
                                        purchase_value,
                                        salvage_value,
                                        context=None):
        val = {}
        for asset in self.browse(cr, uid, ids, context=context):
            if purchase_value:
                val['value_residual'] = purchase_value - salvage_value
            if salvage_value:
                val['value_residual'] = purchase_value - salvage_value
        return {'value': val}

    def _entry_count(self, cr, uid, ids, field_name, arg, context=None):
        res = dict(map(lambda x: (x, 0), ids))
        try:
            for entry in self.browse(cr, uid, ids, context=context):
                res[entry.id] = len(entry.account_move_line_ids)
        except:
            pass
        return res
    _columns = {
        'account_move_line_ids': fields.one2many('account.move.line', 'asset_id', 'Entries', readonly=True, states={'draft':[('readonly',False)]}),
        'entry_count': fields.function(_entry_count, string='# Asset Entries', type='integer'),
        'name': fields.char('Asset Name', size=64, required=True, readonly=True, states={'draft':[('readonly',False)]}),
        'code': fields.char('Reference', size=32, readonly=True, states={'draft':[('readonly',False)]}),
        'purchase_value': fields.float('Gross Value', required=True, readonly=True, states={'draft':[('readonly',False)]}),
        'currency_id': fields.many2one('res.currency','Currency',required=True, readonly=True, states={'draft':[('readonly',False)]}),
        'company_id': fields.many2one('res.company', 'Company', required=True, readonly=True, states={'draft':[('readonly',False)]}),
        'note': fields.text('Note'),
        'category_id': fields.many2one('account.asset.category', 'Asset Category', required=True, change_default=True, readonly=True, states={'draft':[('readonly',False)]}),
        'parent_id': fields.many2one('account.asset.asset', 'Parent Asset', readonly=True, states={'draft':[('readonly',False)]}),
        'child_ids': fields.one2many('account.asset.asset', 'parent_id', 'Children Assets'),
        'purchase_date': fields.date('Purchase Date', required=True, readonly=True, states={'draft':[('readonly',False)]}),
        'state': fields.selection([('draft','Draft'),('open','Running'),('close','Close')], 'Status', required=True,
                                  help="When an asset is created, the status is 'Draft'.\n" \
                                       "If the asset is confirmed, the status goes in 'Running' and the depreciation lines can be posted in the accounting.\n" \
                                       "You can manually close an asset when the depreciation is over. If the last line of depreciation is posted, the asset automatically goes in that status."),
        'active': fields.boolean('Active'),
        'partner_id': fields.many2one('res.partner', 'Partner', readonly=True, states={'draft':[('readonly',False)]}),
        'method': fields.selection([('linear','Linear'),('degressive','Degressive')], 'Computation Method', required=True, readonly=True, states={'draft':[('readonly',False)]}, help="Choose the method to use to compute the amount of depreciation lines.\n"\
            "  * Linear: Calculated on basis of: Gross Value / Number of Depreciations\n" \
            "  * Degressive: Calculated on basis of: Residual Value * Degressive Factor"),
        'method_number': fields.integer('Number of Depreciations', readonly=True, states={'draft':[('readonly',False)]}, help="The number of depreciations needed to depreciate your asset"),
        'method_period': fields.integer('Number of Months in a Period', required=True, readonly=True, states={'draft':[('readonly',False)]}, help="The amount of time between two depreciations, in months"),
        'method_end': fields.date('Ending Date', readonly=True, states={'draft':[('readonly',False)]}),
        'method_progress_factor': fields.float('Degressive Factor', readonly=True, states={'draft':[('readonly',False)]}),
        'value_residual': fields.function(_amount_residual, method=True, digits_compute=dp.get_precision('Account'), string='Residual Value'),
        'method_time': fields.selection([('number','Number of Depreciations'),('end','Ending Date')], 'Time Method', required=True, readonly=True, states={'draft':[('readonly',False)]},
                                  help="Choose the method to use to compute the dates and number of depreciation lines.\n"\
                                       "  * Number of Depreciations: Fix the number of depreciation lines and the time between 2 depreciations.\n" \
                                       "  * Ending Date: Choose the time between 2 depreciations and the date the depreciations won't go beyond."),
        'prorata':fields.boolean('Prorata Temporis', readonly=True, states={'draft':[('readonly',False)]}, help='Indicates that the first depreciation entry for this asset have to be done from the purchase date instead of the first January'),
        'history_ids': fields.one2many('account.asset.history', 'asset_id', 'History', readonly=True),
        'depreciation_line_ids': fields.one2many('account.asset.depreciation.line', 'asset_id', 'Depreciation Lines', readonly=True, states={'draft':[('readonly',False)],'open':[('readonly',False)]}),
        'salvage_value': fields.float('Salvage Value', digits_compute=dp.get_precision('Account'), help="It is the amount you plan to have that you cannot depreciate.", readonly=True, states={'draft':[('readonly',False)]}),
    }
    _defaults = {
        'code':
        lambda obj, cr, uid, context: obj.pool.get('ir.sequence').get(
            cr, uid, 'account.asset.code'),
        'purchase_date':
        lambda obj, cr, uid, context: time.strftime('%Y-%m-%d'),
        'active':
        True,
        'state':
        'draft',
        'method':
        'linear',
        'method_number':
        5,
        'method_time':
        'number',
        'method_period':
        12,
        'method_progress_factor':
        0.3,
        'currency_id':
        lambda self, cr, uid, c: self.pool.get('res.users').browse(
            cr, uid, uid, c).company_id.currency_id.id,
        'company_id':
        lambda self, cr, uid, context: self.pool.get('res.company').
        _company_default_get(cr, uid, 'account.asset.asset', context=context),
    }

    def _check_recursion(self, cr, uid, ids, context=None, parent=None):
        return super(account_asset_asset,
                     self)._check_recursion(cr,
                                            uid,
                                            ids,
                                            context=context,
                                            parent=parent)

    def _check_prorata(self, cr, uid, ids, context=None):
        for asset in self.browse(cr, uid, ids, context=context):
            if asset.prorata and asset.method_time != 'number':
                return False
        return True

    _constraints = [
        (_check_recursion, 'Error ! You cannot create recursive assets.',
         ['parent_id']),
        (_check_prorata,
         'Prorata temporis can be applied only for time method "number of depreciations".',
         ['prorata']),
    ]

    def onchange_category_id(self, cr, uid, ids, category_id, context=None):
        res = {'value': {}}
        asset_categ_obj = self.pool.get('account.asset.category')
        if category_id:
            category_obj = asset_categ_obj.browse(cr,
                                                  uid,
                                                  category_id,
                                                  context=context)
            res['value'] = {
                'method': category_obj.method,
                'method_number': category_obj.method_number,
                'method_time': category_obj.method_time,
                'method_period': category_obj.method_period,
                'method_progress_factor': category_obj.method_progress_factor,
                'method_end': category_obj.method_end,
                'prorata': category_obj.prorata,
            }
        return res

    def onchange_method_time(self,
                             cr,
                             uid,
                             ids,
                             method_time='number',
                             context=None):
        res = {'value': {}}
        if method_time != 'number':
            res['value'] = {'prorata': False}
        return res

    def copy(self, cr, uid, id, default=None, context=None):
        if default is None:
            default = {}
        if context is None:
            context = {}
        default.update({
            'depreciation_line_ids': [],
            'account_move_line_ids': [],
            'history_ids': [],
            'state': 'draft'
        })
        return super(account_asset_asset, self).copy(cr,
                                                     uid,
                                                     id,
                                                     default,
                                                     context=context)

    def _compute_entries(self, cr, uid, ids, period_id, context=None):
        result = []
        period_obj = self.pool.get('account.period')
        depreciation_obj = self.pool.get('account.asset.depreciation.line')
        period = period_obj.browse(cr, uid, period_id, context=context)
        depreciation_ids = depreciation_obj.search(
            cr,
            uid, [('asset_id', 'in', ids),
                  ('depreciation_date', '<=', period.date_stop),
                  ('depreciation_date', '>=', period.date_start),
                  ('move_check', '=', False)],
            context=context)
        if context is None:
            context = {}
        context.update({'depreciation_date': period.date_stop})
        return depreciation_obj.create_move(cr,
                                            uid,
                                            depreciation_ids,
                                            context=context)

    def create(self, cr, uid, vals, context=None):
        asset_id = super(account_asset_asset, self).create(cr,
                                                           uid,
                                                           vals,
                                                           context=context)
        self.compute_depreciation_board(cr, uid, [asset_id], context=context)
        return asset_id

    def open_entries(self, cr, uid, ids, context=None):
        if context is None:
            context = {}
        context.update({
            'search_default_asset_id': ids,
            'default_asset_id': ids
        })
        return {
            'name': _('Journal Items'),
            'view_type': 'form',
            'view_mode': 'tree,form',
            'res_model': 'account.move.line',
            'view_id': False,
            'type': 'ir.actions.act_window',
            'context': context,
        }
Exemplo n.º 40
0
    _columns = {
        'name':fields.char('Memo', size=256),
        'log_ref': fields.char('Check-log Ref', size=128),
<<<<<<< HEAD
#        'origin' : fields.char('Origin', size=128),
        'check_status' :fields.selection([('void','Voided'),('print','Printed'),('re_print','Re-Printed'),('clear','Cleared')]),
        'chk_seq': fields.char("Check Number", size=64, readonly=True),
        'invoice_ids': fields.one2many('account.invoice', 'voucher_id', 'Invoices', ondelete='cascade'),
        'jtype':fields.related('journal_id','type', string="Journal Type", type='selection', selection=[('sale', 'Sale'),('sale_refund','Sale Refund'), ('purchase', 'Purchase'), ('purchase_refund','Purchase Refund'), ('cash', 'Cash'), ('bank', 'Bank and Checks'), ('general', 'General'), ('situation', 'Opening/Closing Situation')],),
    }                                                                                                    
=======
#         'origin' : fields.char('Origin', size=128),
        'check_status' :fields.selection([('void','Voided'),('print','Printed'),('re_print','Re-Printed'),('clear','Cleared')]),
        'chk_seq': fields.char("Check Number", size=64, readonly=True),
        'invoice_ids': fields.one2many('account.invoice', 'voucher_id', 'Invoices', ondelete='cascade'),
        'reference': fields.char('Origin', size=64, readonly=True, states={'draft':[('readonly',False)]}, help="Source document which generated the payment."),
        'jtype':fields.related('journal_id','type', string="Journal Type", type='selection', selection=[('sale', 'Sale'),('sale_refund','Sale Refund'), ('purchase', 'Purchase'), ('purchase_refund','Purchase Refund'), ('cash', 'Cash'), ('bank', 'Bank and Checks'), ('general', 'General'), ('situation', 'Opening/Closing Situation')],),
    }
>>>>>>> c1979f64b3360c86d60e00c92be0271d89f97f2d

    def print_checks(self, cr, uid, ids, context=None):
        check_state = self.browse(cr, uid, ids[0],context=None).check_status
        view_ref = self.pool.get('ir.model.data').get_object_reference(cr, uid, 'account_check_writing', 'view_account_check_write')
        view_id = view_ref and view_ref[1] or False,
        context.update({'active_ids':ids, 'check_state': check_state})
        return {
               'type': 'ir.actions.act_window',
               'name': 'Print Checks',
               'view_mode': 'form',
               'view_type': 'form',
Exemplo n.º 41
0
Arquivo: hr.py Projeto: zop2010/odoo
class hr_employee(osv.osv):
    _name = "hr.employee"
    _description = "Employee"
    _order = 'name_related'
    _inherits = {'resource.resource': "resource_id"}
    _inherit = ['mail.thread']

    _mail_post_access = 'read'

    def _get_image(self, cr, uid, ids, name, args, context=None):
        result = dict.fromkeys(ids, False)
        for obj in self.browse(cr, uid, ids, context=context):
            result[obj.id] = tools.image_get_resized_images(obj.image)
        return result

    def _set_image(self, cr, uid, id, name, value, args, context=None):
        return self.write(cr,
                          uid, [id],
                          {'image': tools.image_resize_image_big(value)},
                          context=context)

    _columns = {
        #we need a related field in order to be able to sort the employee by name
        'name_related': fields.related('resource_id', 'name', type='char', string='Name', readonly=True, store=True),
        'country_id': fields.many2one('res.country', 'Nationality'),
        'birthday': fields.date("Date of Birth"),
        'ssnid': fields.char('SSN No', help='Social Security Number'),
        'sinid': fields.char('SIN No', help="Social Insurance Number"),
        'identification_id': fields.char('Identification No'),
        'otherid': fields.char('Other Id'),
        'gender': fields.selection([('male', 'Male'), ('female', 'Female')], 'Gender'),
        'marital': fields.selection([('single', 'Single'), ('married', 'Married'), ('widower', 'Widower'), ('divorced', 'Divorced')], 'Marital Status'),
        'department_id': fields.many2one('hr.department', 'Department'),
        'address_id': fields.many2one('res.partner', 'Working Address'),
        'address_home_id': fields.many2one('res.partner', 'Home Address'),
        'bank_account_id': fields.many2one('res.partner.bank', 'Bank Account Number', domain="[('partner_id','=',address_home_id)]", help="Employee bank salary account"),
        'work_phone': fields.char('Work Phone', readonly=False),
        'mobile_phone': fields.char('Work Mobile', readonly=False),
        'work_email': fields.char('Work Email', size=240),
        'work_location': fields.char('Office Location'),
        'notes': fields.text('Notes'),
        'parent_id': fields.many2one('hr.employee', 'Manager'),
        'category_ids': fields.many2many('hr.employee.category', 'employee_category_rel', 'emp_id', 'category_id', 'Tags'),
        'child_ids': fields.one2many('hr.employee', 'parent_id', 'Subordinates'),
        'resource_id': fields.many2one('resource.resource', 'Resource', ondelete='cascade', required=True),
        'coach_id': fields.many2one('hr.employee', 'Coach'),
        'job_id': fields.many2one('hr.job', 'Job Title'),
        # image: all image fields are base64 encoded and PIL-supported
        'image': fields.binary("Photo",
            help="This field holds the image used as photo for the employee, limited to 1024x1024px."),
        'image_medium': fields.function(_get_image, fnct_inv=_set_image,
            string="Medium-sized photo", type="binary", multi="_get_image",
            store = {
                'hr.employee': (lambda self, cr, uid, ids, c={}: ids, ['image'], 10),
            },
            help="Medium-sized photo of the employee. It is automatically "\
                 "resized as a 128x128px image, with aspect ratio preserved. "\
                 "Use this field in form views or some kanban views."),
        'image_small': fields.function(_get_image, fnct_inv=_set_image,
            string="Small-sized photo", type="binary", multi="_get_image",
            store = {
                'hr.employee': (lambda self, cr, uid, ids, c={}: ids, ['image'], 10),
            },
            help="Small-sized photo of the employee. It is automatically "\
                 "resized as a 64x64px image, with aspect ratio preserved. "\
                 "Use this field anywhere a small image is required."),
        'passport_id': fields.char('Passport No'),
        'color': fields.integer('Color Index'),
        'city': fields.related('address_id', 'city', type='char', string='City'),
        'login': fields.related('user_id', 'login', type='char', string='Login', readonly=1),
        'last_login': fields.related('user_id', 'date', type='datetime', string='Latest Connection', readonly=1),
    }

    def _get_default_image(self, cr, uid, context=None):
        image_path = get_module_resource('hr', 'static/src/img',
                                         'default_image.png')
        return tools.image_resize_image_big(
            open(image_path, 'rb').read().encode('base64'))

    defaults = {
        'active': 1,
        'image': _get_default_image,
        'color': 0,
    }

    def _broadcast_welcome(self, cr, uid, employee_id, context=None):
        """ Broadcast the welcome message to all users in the employee company. """
        employee = self.browse(cr, uid, employee_id, context=context)
        partner_ids = []
        _model, group_id = self.pool['ir.model.data'].get_object_reference(
            cr, uid, 'base', 'group_user')
        if employee.user_id:
            company_id = employee.user_id.company_id.id
        elif employee.company_id:
            company_id = employee.company_id.id
        elif employee.job_id:
            company_id = employee.job_id.company_id.id
        elif employee.department_id:
            company_id = employee.department_id.company_id.id
        else:
            company_id = self.pool['res.company']._company_default_get(
                cr, uid, 'hr.employee', context=context)
        res_users = self.pool['res.users']
        user_ids = res_users.search(cr,
                                    SUPERUSER_ID,
                                    [('company_id', '=', company_id),
                                     ('groups_id', 'in', group_id)],
                                    context=context)
        partner_ids = list(
            set(u.partner_id.id for u in res_users.browse(
                cr, SUPERUSER_ID, user_ids, context=context)))
        self.message_post(
            cr,
            uid, [employee_id],
            body=
            _('Welcome to %s! Please help him/her take the first steps with Odoo!'
              ) % (employee.name),
            partner_ids=partner_ids,
            subtype='mail.mt_comment',
            context=context)
        return True

    def create(self, cr, uid, data, context=None):
        context = dict(context or {})
        if context.get("mail_broadcast"):
            context['mail_create_nolog'] = True

        employee_id = super(hr_employee, self).create(cr,
                                                      uid,
                                                      data,
                                                      context=context)

        if context.get("mail_broadcast"):
            self._broadcast_welcome(cr, uid, employee_id, context=context)
        return employee_id

    def unlink(self, cr, uid, ids, context=None):
        resource_ids = []
        for employee in self.browse(cr, uid, ids, context=context):
            resource_ids.append(employee.resource_id.id)
        super(hr_employee, self).unlink(cr, uid, ids, context=context)
        return self.pool.get('resource.resource').unlink(cr,
                                                         uid,
                                                         resource_ids,
                                                         context=context)

    def onchange_address_id(self, cr, uid, ids, address, context=None):
        if address:
            address = self.pool.get('res.partner').browse(cr,
                                                          uid,
                                                          address,
                                                          context=context)
            return {
                'value': {
                    'work_phone': address.phone,
                    'mobile_phone': address.mobile
                }
            }
        return {'value': {}}

    def onchange_company(self, cr, uid, ids, company, context=None):
        address_id = False
        if company:
            company_id = self.pool.get('res.company').browse(cr,
                                                             uid,
                                                             company,
                                                             context=context)
            address = self.pool.get('res.partner').address_get(
                cr, uid, [company_id.partner_id.id], ['default'])
            address_id = address and address['default'] or False
        return {'value': {'address_id': address_id}}

    def onchange_department_id(self,
                               cr,
                               uid,
                               ids,
                               department_id,
                               context=None):
        value = {'parent_id': False}
        if department_id:
            department = self.pool.get('hr.department').browse(
                cr, uid, department_id)
            value['parent_id'] = department.manager_id.id
        return {'value': value}

    def onchange_user(self, cr, uid, ids, user_id, context=None):
        work_email = False
        if user_id:
            work_email = self.pool.get('res.users').browse(
                cr, uid, user_id, context=context).email
        return {'value': {'work_email': work_email}}

    def action_follow(self, cr, uid, ids, context=None):
        """ Wrapper because message_subscribe_users take a user_ids=None
            that receive the context without the wrapper. """
        return self.message_subscribe_users(cr, uid, ids, context=context)

    def action_unfollow(self, cr, uid, ids, context=None):
        """ Wrapper because message_unsubscribe_users take a user_ids=None
            that receive the context without the wrapper. """
        return self.message_unsubscribe_users(cr, uid, ids, context=context)

    def get_suggested_thread(self,
                             cr,
                             uid,
                             removed_suggested_threads=None,
                             context=None):
        """Show the suggestion of employees if display_employees_suggestions if the
        user perference allows it. """
        user = self.pool.get('res.users').browse(cr, uid, uid, context)
        if not user.display_employees_suggestions:
            return []
        else:
            return super(hr_employee,
                         self).get_suggested_thread(cr, uid,
                                                    removed_suggested_threads,
                                                    context)

    def _message_get_auto_subscribe_fields(self,
                                           cr,
                                           uid,
                                           updated_fields,
                                           auto_follow_fields=None,
                                           context=None):
        """ Overwrite of the original method to always follow user_id field,
        even when not track_visibility so that a user will follow it's employee
        """
        if auto_follow_fields is None:
            auto_follow_fields = ['user_id']
        user_field_lst = []
        for name, column_info in self._all_columns.items():
            if name in auto_follow_fields and name in updated_fields and column_info.column._obj == 'res.users':
                user_field_lst.append(name)
        return user_field_lst

    def _check_recursion(self, cr, uid, ids, context=None):
        level = 100
        while len(ids):
            cr.execute(
                'SELECT DISTINCT parent_id FROM hr_employee WHERE id IN %s AND parent_id!=id',
                (tuple(ids), ))
            ids = filter(None, map(lambda x: x[0], cr.fetchall()))
            if not level:
                return False
            level -= 1
        return True

    _constraints = [
        (_check_recursion,
         'Error! You cannot create recursive hierarchy of Employee(s).',
         ['parent_id']),
    ]
Exemplo n.º 42
0
            return {}

    def on_change_intervall(self, cr, uid, id, interval):
        ###Function that will update the cron
        ###freqeuence
        self.pool.get("currency.rate.update").save_cron(cr, uid, {"interval_type": interval})
        compagnies = self.search(cr, uid, [])
        for comp in compagnies:
            self.write(cr, uid, comp, {"interval_type": interval})
        return {}

    _inherit = "res.company"
    _columns = {
        ### activate the currency update
        "auto_currency_up": fields.boolean("Automatical update of the currency this company"),
        "services_to_use": fields.one2many("currency.rate.update.service", "company_id", "Currency update services"),
        ###predifine cron frequence
        "interval_type": fields.selection(
            [("days", "Day(s)"), ("weeks", "Week(s)"), ("months", "Month(s)")],
            "Currency update frequence",
            help="""changing this value will
                                                 also affect other compagnies""",
        ),
        ###function field that allows to know the
        ###mutli company currency implementation
        "multi_company_currency_enable": fields.function(
            _multi_curr_enable,
            method=True,
            type="boolean",
            string="Multi company currency",
            help="if this case is not check you can" + " not set currency is active on two company",
Exemplo n.º 43
0
Arquivo: hr.py Projeto: zop2010/odoo
class hr_department(osv.osv):
    _name = "hr.department"
    _description = "HR Department"
    _inherit = ['mail.thread', 'ir.needaction_mixin']

    def _dept_name_get_fnc(self,
                           cr,
                           uid,
                           ids,
                           prop,
                           unknow_none,
                           context=None):
        res = self.name_get(cr, uid, ids, context=context)
        return dict(res)

    _columns = {
        'name':
        fields.char('Department Name', required=True),
        'complete_name':
        fields.function(_dept_name_get_fnc, type="char", string='Name'),
        'company_id':
        fields.many2one('res.company', 'Company', select=True, required=False),
        'parent_id':
        fields.many2one('hr.department', 'Parent Department', select=True),
        'child_ids':
        fields.one2many('hr.department', 'parent_id', 'Child Departments'),
        'manager_id':
        fields.many2one('hr.employee', 'Manager', track_visibility='onchange'),
        'member_ids':
        fields.one2many('hr.employee',
                        'department_id',
                        'Members',
                        readonly=True),
        'jobs_ids':
        fields.one2many('hr.job', 'department_id', 'Jobs'),
        'note':
        fields.text('Note'),
    }

    _defaults = {
        'company_id':
        lambda self, cr, uid, c: self.pool.get('res.company').
        _company_default_get(cr, uid, 'hr.department', context=c),
    }

    def _check_recursion(self, cr, uid, ids, context=None):
        if context is None:
            context = {}
        level = 100
        while len(ids):
            cr.execute(
                'select distinct parent_id from hr_department where id IN %s',
                (tuple(ids), ))
            ids = filter(None, map(lambda x: x[0], cr.fetchall()))
            if not level:
                return False
            level -= 1
        return True

    _constraints = [
        (_check_recursion, 'Error! You cannot create recursive departments.',
         ['parent_id'])
    ]

    def name_get(self, cr, uid, ids, context=None):
        if context is None:
            context = {}
        if not ids:
            return []
        reads = self.read(cr, uid, ids, ['name', 'parent_id'], context=context)
        res = []
        for record in reads:
            name = record['name']
            if record['parent_id']:
                name = record['parent_id'][1] + ' / ' + name
            res.append((record['id'], name))
        return res

    def create(self, cr, uid, vals, context=None):
        # TDE note: auto-subscription of manager done by hand, because currently
        # the tracking allows to track+subscribe fields linked to a res.user record
        # An update of the limited behavior should come, but not currently done.
        manager_id = vals.get("manager_id")
        new_id = super(hr_department, self).create(cr,
                                                   uid,
                                                   vals,
                                                   context=context)
        if manager_id:
            employee = self.pool.get('hr.employee').browse(cr,
                                                           uid,
                                                           manager_id,
                                                           context=context)
            if employee.user_id:
                self.message_subscribe_users(cr,
                                             uid, [new_id],
                                             user_ids=[employee.user_id.id],
                                             context=context)
        return new_id

    def write(self, cr, uid, ids, vals, context=None):
        # TDE note: auto-subscription of manager done by hand, because currently
        # the tracking allows to track+subscribe fields linked to a res.user record
        # An update of the limited behavior should come, but not currently done.
        if isinstance(ids, (int, long)):
            ids = [ids]
        manager_id = vals.get("manager_id")
        if manager_id:
            employee = self.pool.get('hr.employee').browse(cr,
                                                           uid,
                                                           manager_id,
                                                           context=context)
            if employee.user_id:
                self.message_subscribe_users(cr,
                                             uid, [ids],
                                             user_ids=[employee.user_id.id],
                                             context=context)
        return super(hr_department, self).write(cr,
                                                uid,
                                                ids,
                                                vals,
                                                context=context)
Exemplo n.º 44
0
        'cc_charge':fields.boolean('Charge'),
        'cc_info_hide':fields.boolean('Credit Info Hide'),
        'cc_status':fields.text('Status Message'),
        'cc_details_autofill':fields.boolean('Credit Card Details Auto Fill'),
        'cc_reseller':fields.boolean('Reseller'),
        'rel_sale_order_id':fields.many2one('sale.order', 'Related Sale Order'),
        'cc_trans_id':fields.char('Transaction ID', size=128),
        'cc_bank':fields.many2one('res.bank', 'Bank'),
        'cc_details':fields.many2one('res.partner.bank', 'Bank'),
        'cc_length':fields.integer('CC Length'),
        'cc_transaction':fields.boolean('Transaction Done'),
        'key':fields.char('Encryption Key', size=1024,
                          help="The Key used to Encrypt the Credit Card Number"),
        'cc_refund_amt':fields.float('Refund Amt'),
        'is_charged': fields.boolean('CreditCard Charged'),
        'trans_history_ids': fields.one2many('transaction.details', 'voucher_id', 'Transaction History')
    }
    _defaults = {
        'cc_info_hide': lambda * a: True,
        'cc_p_authorize': lambda * a: True,
    }

    def onchange_cc_details(self, cr, uid, ids, cc_details, context={}):
        dic = {}
        if cc_details:
            context['cc_no'] = 'no_mask'
            bank = self.pool.get('res.partner.bank').browse(cr, uid, cc_details, context=context)
            dic['cc_e_d_month'] = bank.cc_e_d_month
            dic['cc_e_d_year'] = bank.cc_e_d_year
            dic['cc_number'] = bank.cc_number
            dic['cc_v'] = bank.cc_v
Exemplo n.º 45
0
Arquivo: hr.py Projeto: zop2010/odoo
class hr_job(osv.Model):
    def _get_nbr_employees(self, cr, uid, ids, name, args, context=None):
        res = {}
        for job in self.browse(cr, uid, ids, context=context):
            nb_employees = len(job.employee_ids or [])
            res[job.id] = {
                'no_of_employee': nb_employees,
                'expected_employees': nb_employees + job.no_of_recruitment,
            }
        return res

    def _get_job_position(self, cr, uid, ids, context=None):
        res = []
        for employee in self.pool.get('hr.employee').browse(cr,
                                                            uid,
                                                            ids,
                                                            context=context):
            if employee.job_id:
                res.append(employee.job_id.id)
        return res

    _name = "hr.job"
    _description = "Job Position"
    _inherit = ['mail.thread']
    _columns = {
        'name':
        fields.char('Job Name', required=True, select=True),
        'expected_employees':
        fields.function(
            _get_nbr_employees,
            string='Total Forecasted Employees',
            help=
            'Expected number of employees for this job position after new recruitment.',
            store={
                'hr.job': (lambda self, cr, uid, ids, c=None: ids,
                           ['no_of_recruitment'], 10),
                'hr.employee': (_get_job_position, ['job_id'], 10),
            },
            type='integer',
            multi='_get_nbr_employees'),
        'no_of_employee':
        fields.function(
            _get_nbr_employees,
            string="Current Number of Employees",
            help='Number of employees currently occupying this job position.',
            store={
                'hr.employee': (_get_job_position, ['job_id'], 10),
            },
            type='integer',
            multi='_get_nbr_employees'),
        'no_of_recruitment':
        fields.integer('Expected New Employees',
                       copy=False,
                       help='Number of new employees you expect to recruit.'),
        'no_of_hired_employee':
        fields.integer(
            'Hired Employees',
            copy=False,
            help=
            'Number of hired employees for this job position during recruitment phase.'
        ),
        'employee_ids':
        fields.one2many('hr.employee',
                        'job_id',
                        'Employees',
                        groups='base.group_user'),
        'description':
        fields.text('Job Description'),
        'requirements':
        fields.text('Requirements'),
        'department_id':
        fields.many2one('hr.department', 'Department'),
        'company_id':
        fields.many2one('res.company', 'Company'),
        'state':
        fields.selection(
            [('open', 'Recruitment Closed'),
             ('recruit', 'Recruitment in Progress')],
            string='Status',
            readonly=True,
            required=True,
            track_visibility='always',
            copy=False,
            help=
            "By default 'Closed', set it to 'In Recruitment' if recruitment process is going on for this job position."
        ),
        'write_date':
        fields.datetime('Update Date', readonly=True),
    }

    _defaults = {
        'company_id':
        lambda self, cr, uid, ctx=None: self.pool.get('res.company').
        _company_default_get(cr, uid, 'hr.job', context=ctx),
        'state':
        'open',
    }

    _sql_constraints = [
        ('name_company_uniq', 'unique(name, company_id, department_id)',
         'The name of the job position must be unique per department in company!'
         ),
        ('hired_employee_check',
         "CHECK ( no_of_hired_employee <= no_of_recruitment )",
         "Number of hired employee must be less than expected number of employee in recruitment."
         ),
    ]

    def set_recruit(self, cr, uid, ids, context=None):
        for job in self.browse(cr, uid, ids, context=context):
            no_of_recruitment = job.no_of_recruitment == 0 and 1 or job.no_of_recruitment
            self.write(cr,
                       uid, [job.id], {
                           'state': 'recruit',
                           'no_of_recruitment': no_of_recruitment
                       },
                       context=context)
        return True

    def set_open(self, cr, uid, ids, context=None):
        self.write(cr,
                   uid,
                   ids, {
                       'state': 'open',
                       'no_of_recruitment': 0,
                       'no_of_hired_employee': 0
                   },
                   context=context)
        return True

    def copy(self, cr, uid, id, default=None, context=None):
        if default is None:
            default = {}
        if 'name' not in default:
            job = self.browse(cr, uid, id, context=context)
            default['name'] = _("%s (copy)") % (job.name)
        return super(hr_job, self).copy(cr,
                                        uid,
                                        id,
                                        default=default,
                                        context=context)

    # ----------------------------------------
    # Compatibility methods
    # ----------------------------------------
    _no_of_employee = _get_nbr_employees  # v7 compatibility
    job_open = set_open  # v7 compatibility
    job_recruitment = set_recruit  # v7 compatibility
Exemplo n.º 46
0
                            kail.write({'reason':e})
                            done = False
            if done: 
                kai.write({'state':'done'})
        pass
        
    IMPORT_TYPE = (('lq','Liquidation'),('usage','Usage'),('spec','Specification'))
    _columns={
              'name':fields.date("Import Date", 
                                    states={'done':[('readonly',True)]}, required=True),              
              'remarks':fields.char('Remarks',size=256, 
                                    states={'done':[('readonly',True)]}),                                                               
                
              'state':fields.selection((('draft','Draft'),('done','Completed')),'State',readonly=True),
              
              'detail_ids':fields.one2many('kderp.import.asset.detail','import_id','Details',states={'done':[('readonly',True)]}),
              'detail_spec_ids':fields.one2many('kderp.import.asset.detail','import_id','Details',states={'done':[('readonly',True)]}),
              'detail_usage_ids':fields.one2many('kderp.import.asset.detail','import_id','Details',states={'done':[('readonly',True)]}),
              'import_type':fields.selection(IMPORT_TYPE,'Import type',states={'done':[('readonly',True)]}),
              }
    _defaults={
               'name':lambda *a: time.strftime('%Y-%m-%d'),
               'state':lambda *a: 'draft'
               }    
    
kderp_asset_import()  

class kderp_import_asset_detail(Model):    
    _name = 'kderp.import.asset.detail'
    _rec_name = 'asset_id'
    
Exemplo n.º 47
0
class ElectricComponent(electric_component_base):
    _inherit = 'component.component'
    _description = 'Components'

    def electric_info(self, cr, uid, ids, field_name, arg, context=None):
        return super(ElectricComponent, self).electric_info(cr, uid, ids, field_name, arg, context=context)

    # def _electric_info(self, cr, uid, ids, field_name, arg, context=None):
    #     res = dict.fromkeys(ids, "")
    #     for component in self.browse(cr, uid, ids, context=context):
    #         cmodel = self.pool[component.component_model]
    #         for c in cmodel.browse(cr, uid, [('delegated_id' in ids)], context=context):
    #             if 'component_info' in c:
    #                 res[c.delegated_id] = c.component_info;
    #     return res;

    def _get_attachment_number(self, cr, uid, ids, field_name, arg, context=None):
        res = dict.fromkeys(ids, 0)
        return res

    def _test_count(self, cr, uid, ids, field_name, arg, context=None):
        res = dict.fromkeys(ids, 0)
        for component in self.browse(cr, uid, ids, context=context):
            if component.component_model_test in self.pool:
                if 'delegated_id' in component:
                    def_id = component.id
                else:
                    true_components = self.pool[component.component_model]
                    def_id = true_components.search(cr, uid, [('delegated_id', '=', component.id)], limit=1)
                count = self.pool[component.component_model_test].search_count(cr, uid, [('component_id',"=",def_id)], context);
                res[component.id] = count
        return res

    def _get_attachment_number(self, cr, uid, ids, field_name, arg, context=None):
        res = dict.fromkeys(ids, 0)
        component_docs = self.pool['ir.attachment']
        for docs in component_docs.read_group(cr, uid, [('res_model', '=', 'component.component'), ('res_id', 'in', ids)],
                                          ['res_id'], ['res_id'], context):
            res[docs['res_id']] = component_docs.search_count(cr,uid, [('res_id', '=', docs['res_id'])], context=context)
        return res

    def fields_view_get(self, cr, uid, view_id=None, view_type='form', context=None, toolbar=False, submenu=False):
        result = super(ElectricComponent, self).fields_view_get(cr, uid, view_id, view_type, context, toolbar, submenu)
        return result

    _columns = {
        'electric_info': fields.function(electric_info, 'Information', type='char'),
        'customer_id': fields.many2one('res.partner', 'Customer'),
        'component_model': fields.char('Component Model'),
        'component_model_test': fields.char('Component Model Test'),
        'test_count': fields.function(_test_count, string='Test Sheets', type='integer'),
        'attachment_number': fields.function(_get_attachment_number, string="Documents Attached", type="integer"),
        'attachment_ids': fields.one2many('ir.attachment', 'res_id', domain=[('res_model', '=', 'component.component')], string='Attachments')
    }

    @api.model
    def create(self, values):
        # values = self._test_image_small(values)
        return super(ElectricComponent, self).create(values)

    @api.multi
    def write(self, vals):
        # self._test_image_small(vals)
        res = super(ElectricComponent, self).write(vals)
        return res

    def can_create(self):
        return self.electric_component_type != 'all_components'

    _defaults = {
        'electric_component_type': 'all_components',
    }

    def unlink(self, cr, uid, ids, context=None):
        for component in self.browse(cr, uid, ids, context=context):
            if not('delegated_id' in component):
                true_components = self.pool[component.component_model]
                def_id = true_components.search(cr, uid, [('delegated_id', '=', component.id)], limit=1)
                self.pool[component.component_model].unlink(cr, uid, def_id, context=context)
        return super(ElectricComponent, self).unlink(cr, uid, ids, context)
    _description = "Import Inventory"

    def _default_location(self, cr, uid, ids, context=None):
        try:
            loc_model, location_id = self.pool.get('ir.model.data').get_object_reference(cr, uid, 'stock', 'stock_location_stock')
        except ValueError, e:
            return False
        return location_id or False

    _columns = {
        'location_id': fields.many2one('stock.location', 'Location', required=True),
        'import_file': fields.binary('File', filters="*.xls"),
        #to consider the product current inventory or not, if yes then add the current inventory to the upload excel quantity as the quantity to do physical inventory
        'consider_inventory': fields.boolean('Consider Current Inventory', select=True), 
        'all_done': fields.boolean('All Data Imported', readonly=True, select=True), 
        'result_line': fields.one2many('stock.import.inventory.result', 'import_id', 'Importing Result', readonly=True), 
        'file_template': fields.binary('Template File', readonly=True),
        'file_template_name': fields.char('Template File Name'),
    }
    
    def _get_template(self, cr, uid, context):
        cur_path = os.path.split(os.path.realpath(__file__))[0]
        path = os.path.join(cur_path,'stock_import_template.xls')
        data = open(path,'rb').read().encode('base64')
#        data = os.path.getsize(path)
        return data
    
    _defaults = {
        'location_id': _default_location,
        'file_template': _get_template,
        'file_template_name': 'stock_import_template.xls'
Exemplo n.º 49
0
class periodic_inventory_valuation(osv.osv):
    _name = "periodic.inventory.valuation"
    _description = "Periodic Inventory Valuation"
    _columns = {
        'name':
        fields.char('Name', size=64, required=True, help=""),
        'move_id':
        fields.many2one(
            'account.move',
            'Journal Entry',
            help=
            'Journal Entry For this Periodic Inventory Valuation Document, it will be created when Document is Posted'
        ),
        'company_id':
        fields.many2one('res.company',
                        'Company',
                        help='Company for this Document'),
        'period_id':
        fields.many2one(
            'account.period',
            'Period',
            help=
            'Accounting Period to be used when creating Journal Entries and Accounting Entries'
        ),
        'inventory_valuation_journal_id':
        fields.many2one(
            'account.journal',
            'Journal',
            help=
            'Accounting Journal to be used when creating Journal Entries and Accounting Entries'
        ),
        'currency_id':
        fields.many2one(
            'res.currency',
            'Currency',
            help=
            'Currency to be used when creating Journal Entries and Accounting Entries'
        ),
        'date':
        fields.date(
            'Valuation Date',
            help=
            'Date to be used when creating Journal Entries and Accounting Entries'
        ),
        'state':
        fields.selection([('draft', 'Readying Valuation'),
                          ('confirm', 'Ready to Valuate'),
                          ('done', 'Valuated Inventory')]),
        'product_ids':
        fields.many2many('product.product',
                         'piv_prod_rel',
                         'product_id',
                         'piv_id',
                         'Valuating Products',
                         help='Products to be Valuated'),
        'stock_move_ids':
        fields.many2many('stock.move',
                         'piv_sm_rel',
                         'stock_move_id',
                         'piv_id',
                         'Stock Moves',
                         help='Stock Moves to be used as Control Sample'),
        'ail_ids':
        fields.many2many(
            'account.invoice.line',
            'piv_ail_rel',
            'ail_id',
            'piv_id',
            'Account Invoice Lines',
            help='Account Invoice Lines to be used to Valuate Inventory'),
        'aml_ids':
        fields.many2many(
            'account.move.line',
            'piv_aml_rel',
            'aml_id',
            'piv_id',
            'Account Move Lines',
            help='Account Move Lines to be Created to Valuate Inventory'),
        'pivl_ids':
        fields.one2many(
            'periodic.inventory.valuation.line',
            'piv_id',
            'Periodic Inventory Valuation Lines',
            help=
            'Periodic Inventory Valuation Lines created to valuate Inventory'),
        'first':
        fields.boolean('First run'),
    }
    _defaults = {
        'state':
        'draft',
        'company_id':
        lambda s, c, u, ctx: s.pool.get('res.users').browse(
            c, u, u, context=ctx).company_id.id,
        'first':
        False,
        'currency_id':
        lambda s, c, u, ctx: s.pool.get('res.users').browse(
            c, u, u, context=ctx).company_id.currency_id.id,
        'inventory_valuation_journal_id':
        lambda s, c, u, ctx: s.pool.get('res.users').browse(
            c, u, u, context=ctx).company_id.inventory_valuation_journal_id.id,
    }

    def get_period(self, cr, uid, ids, date, context=None):
        if context is None:
            context = {}

        period_obj = self.pool.get('account.period')
        period_ids = period_obj.find(cr, uid, dt=date, context=context)
        period_ids = period_obj.search(cr,
                                       uid, [('id', 'in', period_ids),
                                             ('special', '=', False)],
                                       context=context)
        period_ids = period_ids and period_ids[0] or False
        if not period_ids:
            raise osv.except_osv(
                _('Error!'),
                _('There is no fiscal year defined for this date.\nPlease create one from the configuration of the accounting menu.'
                  ))

        return period_ids

    def exchange(self,
                 cr,
                 uid,
                 ids,
                 from_amount,
                 to_currency_id,
                 from_currency_id,
                 exchange_date,
                 context=None):
        if context is None:
            context = {}
        if from_currency_id == to_currency_id:
            return from_amount
        curr_obj = self.pool.get('res.currency')
        context['date'] = exchange_date
        return curr_obj.compute(cr,
                                uid,
                                from_currency_id,
                                to_currency_id,
                                from_amount,
                                context=context)

    def validate_data(self, cr, uid, ids, date, context=None):
        if context is None:
            context = {}

        if ids:
            if type(ids) is list:
                peri_inv_allowed = self.search(cr,
                                               uid, [('id', '!=', ids[0])],
                                               order='id desc',
                                               limit=1,
                                               context=context)
            else:
                peri_inv_allowed = self.search(cr,
                                               uid, [('id', '!=', ids)],
                                               order='id desc',
                                               limit=1,
                                               context=context)
        else:
            peri_inv_allowed = self.search(cr,
                                           uid, [],
                                           order='id desc',
                                           limit=1,
                                           context=context)

        all_per_inv = self.browse(cr, uid, peri_inv_allowed, context=context)
        #$$$
        for i in all_per_inv:
            if date <= i.date:
                raise osv.except_osv(
                    'Record with this data existing !',
                    'Can not create a record with repeated date')

        return True

    def write(self, cr, uid, ids, vals, context=None):
        if context is None:
            context = {}

        if type(ids) is list:
            brw_per_inv = self.browse(cr, uid, ids[0], context=context)
        else:
            brw_per_inv = self.browse(cr, uid, ids, context=context)

        if brw_per_inv.state == 'done':
            raise osv.except_osv('Can not write the record',
                                 'When a stock is done, can not be write')

        self.validate_data(cr, uid, ids, brw_per_inv.date, context=context)

        vals['period_id'] = self.get_period(cr,
                                            uid,
                                            ids,
                                            vals.get('date'),
                                            context=context)
        return super(periodic_inventory_valuation, self).write(cr,
                                                               uid,
                                                               ids,
                                                               vals,
                                                               context=context)

    def create(self, cr, uid, vals, context=None):
        if context is None:
            context = {}

        inv = self.pool.get('res.users').browse(
            cr, uid, uid,
            context=context).company_id.inventory_valuation_journal_id
        if not inv.id:
            raise osv.except_osv(
                'You need to define the journal',
                'Must be defined in the company the journal to generate the journal items for periodic inventory'
            )

        self.validate_data(cr, uid, False, vals.get('date'), context=context)
        vals['period_id'] = self.get_period(cr,
                                            uid,
                                            False,
                                            vals.get('date'),
                                            context=context)
        return super(periodic_inventory_valuation,
                     self).create(cr, uid, vals, context=context)

    def unlink(self, cr, uid, ids, context=None):
        if context is None:
            context = {}
        brw_per_inv = self.browse(cr, uid, ids[0], context=context)

        if brw_per_inv.state == 'done':
            raise osv.except_osv('Can not delete the record',
                                 'When a stock is done, can not be deleted')

        return super(periodic_inventory_valuation,
                     self).unlink(cr, uid, ids, context=context)

    def load_valuation_items(self, cr, uid, ids, context=None):
        context = context or {}
        ids = isinstance(ids, (int, long)) and [ids] or ids
        prod_obj = self.pool.get('product.product')

        prod_ids = prod_obj.search(cr,
                                   uid, [
                                       ('type', '=', 'product'),
                                       ('valuation', '=', 'manual_periodic'),
                                   ],
                                   context=context)

        period_obj = self.pool.get('account.period')
        piv_brw = self.browse(cr, uid, ids[0], context=context)
        date = piv_brw.date
        company_id = piv_brw.company_id.id
        currency_id = piv_brw.currency_id.id

        inventory_valuation_journal_id = piv_brw.company_id.inventory_valuation_journal_id.id

        period_id = piv_brw.period_id.id

        inv_obj = self.pool.get('account.invoice')

        # Se obtiene la linea del producto del registro anterior
        if type(ids) is list:
            piv_id = self.search(cr,
                                 uid, [('id', '!=', ids[0]),
                                       ('state', '=', 'done')],
                                 order='id desc',
                                 limit=1,
                                 context=context)
        else:
            piv_id = self.search(cr,
                                 uid, [('id', '!=', ids),
                                       ('state', '=', 'done')],
                                 order='id desc',
                                 limit=1,
                                 context=context)

        piv = self.browse(cr, uid, ids[0], context=context)
        fecha_now = datetime.datetime.strptime(piv.date, '%Y-%m-%d')

        if piv_id:
            piv_id = piv_id[0]
            piv_before = self.browse(cr, uid, piv_id, context=context)
            fecha_before = datetime.datetime.strptime(piv_before.date,
                                                      '%Y-%m-%d')
        else:
            fecha_before = False

        inv_ids = []

        if fecha_before:
            inv_ids = inv_obj.search(cr,
                                     uid, [('state', 'in', ('open', 'paid')),
                                           ('date_invoice', '>', fecha_before),
                                           ('date_invoice', '<=', fecha_now),
                                           ('company_id', '=', company_id)],
                                     context=context)
        else:
            inv_ids = inv_obj.search(cr,
                                     uid, [('state', 'in', ('open', 'paid')),
                                           ('date_invoice', '<=', fecha_now),
                                           ('company_id', '=', company_id)],
                                     context=context)

        if not inv_ids:
            raise osv.except_osv(
                _('Error!'),
                _('There are no invoices defined for this period.\nMake sure you are using the right date.'
                  ))
        ail_obj = self.pool.get('account.invoice.line')
        ail_ids = ail_obj.search(cr,
                                 uid, [('invoice_id', 'in', inv_ids),
                                       ('product_id', 'in', prod_ids)],
                                 context=context)
        if not ail_ids:
            raise osv.except_osv(
                _('Error!'),
                _('There are no invoices lines defined for this period.\nMake sure you are using the right date.'
                  ))

        period_brw = period_obj.browse(cr, uid, period_id, context=context)
        date_start = period_brw.date_start
        date_stop = period_brw.date_stop

        sl_obj = self.pool.get('stock.location')
        int_sl_ids = sl_obj.search(cr,
                                   uid, [('usage', '=', 'internal')],
                                   context=context)
        ext_sl_ids = sl_obj.search(cr,
                                   uid, [('usage', '!=', 'internal')],
                                   context=context)

        sm_obj = self.pool.get('stock.move')
        incoming_sm_ids = sm_obj.search(
            cr,
            uid, [
                ('state', '=', 'done'),
                ('company_id', '=', company_id),
                ('location_id', 'in', ext_sl_ids),
                ('location_dest_id', 'in', int_sl_ids),
                ('date', '>=', date_start),
                ('date', '<=', date_stop),
            ],
            context=context)
        outgoing_sm_ids = sm_obj.search(
            cr,
            uid, [
                ('state', '=', 'done'),
                ('company_id', '=', company_id),
                ('location_id', 'in', int_sl_ids),
                ('location_dest_id', 'in', ext_sl_ids),
                ('date', '>=', date_start),
                ('date', '<=', date_stop),
            ],
            context=context)

        # Se establecen parametros para usar en los calculos
        periodic_line = self.pool.get('periodic.inventory.valuation.line')
        lineas = []
        move_id = False
        state = 'draft'

        # Si no se han hecho calculos, se cargan datos iniciales, aqui la condicion deberia ser si el estado es draft
        # Se debe validar que si es el primer registro cargar datos en 0, si no es el primer registro entonces tomar
        # valores del ultimo registro
        if not piv.first:
            state = 'confirm'

            pivline_init_ids = []
            # Se itera sobre los productos que sean de tipo producto y con valuation tipo manual_periodic
            for prod_id in prod_ids:
                prod = prod_obj.browse(cr, uid, prod_id, context=context)

                piv_line_id = False

                if piv_id:
                    piv_line_id = periodic_line.search(
                        cr,
                        uid, [('piv_id', '=', piv_id),
                              ('product_id', '=', prod_id)],
                        context=context)

                # condicional aqui de piv_line_brw, puede que no exista
                if piv_line_id:
                    piv_line_brw = periodic_line.browse(cr,
                                                        uid,
                                                        piv_line_id,
                                                        context=context)[0]
                    line_qty_init = piv_line_brw.qty_final
                    line_average_cost = piv_line_brw.average_cost
                    line_valuation = piv_line_brw.valuation
                else:
                    line_qty_init = 0.0
                    line_average_cost = 0.0
                    line_valuation = 0.0

                # Guardar informacion de la linea piv a crear en el registro actual
                pivline_init_ids.append(
                    periodic_line.create(cr,
                                         uid, {
                                             'piv_id': ids[0],
                                             'product_id': prod_id,
                                             'qty_init': line_qty_init,
                                             'qty_final': 0.0,
                                             'qty_sale': 0.0,
                                             'qty_purchase': 0.0,
                                             'uom_id': prod.uom_id.id,
                                             'average_cost': line_average_cost,
                                             'valuation': line_valuation,
                                         },
                                         context=context))

            # Cargar lineas nuevas en el registro actual
            self.write(cr,
                       uid,
                       ids[0], {
                           'pivl_ids': [(6, 0, pivline_init_ids)],
                       },
                       context=context)
        else:
            state = 'done'
            product_price_purs = {}
            product_price_sales = {}

            # Se iteran que esten pagadas o abiertas y que esten dentro del periodo al que corresponde
            # la fecha actual
            product_price = []
            for ail_id in ail_ids:
                ail = ail_obj.browse(cr, uid, ail_id, context=context)

                # si la factura se relaciona a la lista de productos que se filtraron
                if ail.product_id.id in prod_ids:

                    produc_obj = prod_obj.browse(cr,
                                                 uid,
                                                 ail.product_id.id,
                                                 context=context)

                    price_unit = self.exchange(cr,
                                               uid,
                                               ids,
                                               ail.price_unit,
                                               ail.invoice_id.currency_id.id,
                                               currency_id,
                                               date,
                                               context=context)

                    if ail.invoice_id.type == 'in_invoice':
                        p_p_pur = {'qty': ail.quantity, 'price': price_unit}
                        if product_price_purs.get(ail.product_id.id, False):
                            product_price_purs[ail.product_id.id].append(
                                p_p_pur)
                        else:
                            product_price_purs[ail.product_id.id] = [p_p_pur]
                    elif ail.invoice_id.type == 'out_invoice':
                        p_p_sale = {'qty': ail.quantity, 'price': price_unit}
                        if product_price_sales.get(ail.product_id.id, False):
                            product_price_sales[ail.product_id.id].append(
                                p_p_sale)
                        else:
                            product_price_sales[ail.product_id.id] = [p_p_sale]
                    else:
                        print ail.invoice_id.type
                    product_price.append(ail.product_id.id)

            lineas = []
            for i in prod_ids:

                prod = prod_obj.browse(cr, uid, i, context=context)
                val_line_ids = periodic_line.search(cr,
                                                    uid,
                                                    [('product_id', '=', i),
                                                     ('piv_id', '=', ids[0])],
                                                    context=context)
                val_line = periodic_line.browse(cr,
                                                uid,
                                                val_line_ids,
                                                context=context)[0]
                #~~~~~~~~~~~
                qty_pur = 0
                costo = 0.0
                qty_sale = 0
                # Si el producto fue parte de una compra
                if product_price_purs.get(i, False):
                    for j in product_price_purs[i]:
                        costo += j.get('qty') * j.get('price')
                        qty_pur += j.get('qty')

                # Si el producto fue parte de una venta
                if product_price_sales.get(i, False):
                    for k in product_price_sales[i]:
                        #inventario_final -= k.get('qty')
                        qty_sale += k.get('qty')
                inventario_final = val_line.qty_init + qty_pur - qty_sale

                costo += val_line.valuation
                qty = val_line.qty_init + qty_pur  # este val_line.init es el final de la linea anterior

                if qty == 0:
                    costo_promedio = 0
                else:
                    costo_promedio = round(costo / qty, 2)

                valuation = (val_line.valuation) + (
                    qty_pur * costo_promedio) - (qty_sale * costo_promedio)
                # ~~~~~~~~~~~

                # Algo pasa con prod.property_account_expense y prod.property_account_income
                # Establezco los diarios para hacer los asientos

                # Product valuation and journal item amount
                journal_item = valuation - val_line.valuation

                debit = journal_item > 0 and journal_item or 0.0
                credit = journal_item < 0 and (journal_item * -1) or 0.0

                if journal_item != 0:
                    if prod.property_account_expense:
                        account_expense = prod.property_account_expense
                    else:
                        account_expense = prod.product_tmpl_id.categ_id.property_account_expense_categ

                    account_income = prod.product_tmpl_id.categ_id.property_stock_valuation_account_id

                    if not account_expense or not account_income:
                        raise osv.except_osv(
                            _('Error!'),
                            _('Product Account.\nThere are no accounts defined for the product %s.'
                              % (prod.name)))

                    context['journal_id'] = inventory_valuation_journal_id
                    context['period_id'] = period_id
                    move_line = {
                        'name': 'GANANCIA O PERDIDA DE INVENTARIO',
                        'partner_id': False,
                        'product_id': prod.id,
                        'account_id': account_income.id,
                        'move_id': False,
                        'journal_id': inventory_valuation_journal_id,
                        'period_id': period_id,
                        'date': date_stop,
                        'debit': debit,
                        'credit': credit,
                    }

                    line_id = self.pool.get('account.move.line').create(
                        cr, uid, move_line, context=context)
                    lineas.append(line_id)

                    move_line['account_id'] = account_expense.id
                    move_line['debit'] = credit
                    move_line['credit'] = debit

                    line_id = self.pool.get('account.move.line').create(
                        cr, uid, move_line, context=context)
                    lineas.append(line_id)

                periodic_line.write(
                    cr, uid, val_line.id, {
                        'average_cost': costo_promedio,
                        'valuation': valuation,
                        'qty_sale': qty_sale,
                        'qty_purchase': qty_pur,
                        'qty_final': inventario_final,
                    })
            ##############################################################
            if lineas:
                move_id = self.pool.get('account.move.line').browse(
                    cr, uid, lineas[0], context=context).move_id.id
            else:
                move_id = False

        self.write(
            cr,
            uid,
            ids[0], {
                'product_ids': [(6, 0, prod_ids)],
                'ail_ids': [(6, 0, ail_ids)],
                'date': date or fields.date.today(),
                'stock_move_ids': [(6, 0, incoming_sm_ids + outgoing_sm_ids)],
                'first': True,
                'aml_ids': [(6, 0, lineas)],
                'move_id': move_id,
                'state': state,
            },
            context=context)

        return True
Exemplo n.º 50
0
                    _logger.info("Carrier %s: %s", carrier.name, e.name)
                    price = 0.0
              else:
                  price = 0.0
            res[carrier.id] = {
                'price': price,
                'available': available
            }
        return res

    _columns = {
        'name': fields.char('Delivery Method', required=True, translate=True),
        'sequence': fields.integer('Sequence', help="Determine the display order"),
        'partner_id': fields.many2one('res.partner', 'Transport Company', required=True, help="The partner that is doing the delivery service."),
        'product_id': fields.many2one('product.product', 'Delivery Product', required=True),
        'grids_id': fields.one2many('delivery.grid', 'carrier_id', 'Delivery Grids'),
        'available' : fields.function(get_price, string='Available',type='boolean', multi='price',
            help="Is the carrier method possible with the current order."),
        'price' : fields.function(get_price, string='Price', multi='price'),
        'active': fields.boolean('Active', help="If the active field is set to False, it will allow you to hide the delivery carrier without removing it."),
        'normal_price': fields.float('Normal Price', help="Keep empty if the pricing depends on the advanced pricing per destination"),
        'free_if_more_than': fields.boolean('Free If Order Total Amount Is More Than', help="If the order is more expensive than a certain amount, the customer can benefit from a free shipping"),
        'amount': fields.float('Amount', help="Amount of the order to benefit from a free shipping, expressed in the company currency"),
        'use_detailed_pricelist': fields.boolean('Advanced Pricing per Destination', help="Check this box if you want to manage delivery prices that depends on the destination, the weight, the total of the order, etc."),
        'pricelist_ids': fields.one2many('delivery.grid', 'carrier_id', 'Advanced Pricing'),
    }

    _defaults = {
        'active': 1,
        'free_if_more_than': False,
        'sequence': 10,
Exemplo n.º 51
0
class create_purchase_requestion(osv.osv_memory):
    """ 
    class to manage the wizard of creating the purchase requestion """

    _description='create purchase requestion'
    _name = 'create.purchase.requestion'
    _columns = {
                'srock_exchange': fields.many2one('exchange.order', 'Stock Exchange', readonly=True),
                'current_date': fields.date('Current Date', readonly=True),
                'products_ids':fields.one2many('create.purchase.requestion.products', 'wizard_id' , 'Products'),                
                }
    
    _defaults = {
                #'srock_exchange':lambda cr,uid,ids,context:context['active_id'] or False,
                'current_date': lambda *a: time.strftime('%Y-%m-%d'),
                }

    def default_get(self, cr, uid, fields, context=None):
        """ 
        To get default values for the object.

        @return: A dictionary which of fields with values.
        """
        if context is None:
            context = {}

        exchang_obj = self.pool.get('exchange.order')
        res ={}
        exchang_ids = context.get('active_ids', [])
        if not exchang_ids:
            return res

        result = []
        for req in exchang_obj.browse(cr, uid, exchang_ids, context=context):
            for product in req.order_line:
                result.append(self.__create_products(product))
        res.update({'products_ids': result})
        if 'current_date' in fields:
            res.update({'current_date': time.strftime('%Y-%m-%d %H:%M:%S')})
        return res

    def __create_products(self, product):
        product_memory = {
            'product_id' : product.product_id.id,
            'product_qty':product.product_qty,
            'stock_exchange_line' : product.id,
            'description': product.notes,
        }
        return product_memory

    def create_purchase_requestion(self, cr, uid, ids, context=None):
        #TODO change the state of the purchase requestion to quotes and let the wizard in specefic state
        """
        Button function to create purchase requestion from the
 
        @return: Purchase Requestion Id
        """        
        purchase_requestion_obj = self.pool.get('ireq.m')
        exchange = self.pool.get('exchange.order').browse(cr, uid, context['active_id'])
        requestion_lines_obj = self.pool.get('ireq.products')
        prod = self.pool.get('product.product')
        wf_service = netsvc.LocalService("workflow")
        if exchange.purchase_requestion_id:
            raise  osv.except_osv(_('Warning'), _('You allredy create a purchase requestion for this exchange order '))
        for wizard in self.browse(cr, uid, ids):
            requestion_id =  purchase_requestion_obj.create(cr, uid, {'company_id': exchange.company_id.id,
                                                                      'user': context['uid'],
                                                                      'cat_id':exchange.category_id.id or False,
                                                                      'ir_ref': exchange.name, 
                                                                      'department_id' : exchange.department_id.id,
                                                                      'exchane_order_id':[(4, exchange.id)],})
            for wizard_lines in wizard.products_ids:
                product = prod.browse(cr, uid,wizard_lines.product_id.id)
                requestion_lines_obj.create(cr, uid, {'pr_rq_id':requestion_id,
                                                      'product_id': wizard_lines.product_id.id,
                                                      'name': product.name,
                                                      'product_qty': wizard_lines.product_qty,
                                                      'product_uom': product.uom_po_id.id, 
                                                      'desc': wizard_lines.description,})
         
        exchange.write({'purchase_requestion_id':requestion_id , 'state' : 'wait_purchase' }) 
        wf_service.trg_validate(uid, 'ireq.m', requestion_id, 'draft', cr)
        return requestion_id
Exemplo n.º 52
0
                cr,
                uid,
                save_cron
            )

        return super(res_company, self).write(cr, uid, ids, vals, context=context)



    _inherit = "res.company"
    _columns = {
        ### activate the currency update
        'auto_currency_up': fields.boolean('Automatical update of the currency this company'),
        'services_to_use' : fields.one2many(
                                            'currency.rate.update.service',
                                            'company_id',
                                            'Currency update services'
                                            ),
        ###predifine cron frequence
        'interval_type': fields.selection(
                                                [
                                                    ('days','Day(s)'),
                                                    ('weeks', 'Week(s)'),
                                                    ('months', 'Month(s)')
                                                ],
                                                'Currency update frequence',
                                                help="""changing this value will
                                                 also affect other compagnies"""
                                            ),
        ###function field that allows to know the
        ###mutli company currency implementation
Exemplo n.º 53
0
class dym_penyerahan_bpkb(osv.osv):
    _name = "dym.penyerahan.bpkb"

    def _get_default_branch(self,cr,uid,ids,context=None):
        user_obj = self.pool.get('res.users')        
        user = user_obj.browse(cr,uid,uid)
        if user.branch_type!='HO':
            if not user.branch_id:
                return False
            return user.branch_id.id
        else:
            return False

    @api.depends('penyerahan_line.name')
    def _amount_all(self):
        for ib in self:
            amount_total = 0.0
            for line in ib.penyerahan_line:
                ib.update({
                    'total_record': len(ib.penyerahan_line),
                })
    
    _columns = {
        'name': fields.char('No Reference', readonly=True),
        'branch_id': fields.many2one('dym.branch', string='Branch', required=True),
        'division':fields.selection([('Unit','Showroom')], 'Division', change_default=True, select=True),
        'penerima':fields.char('Penerima'),
        'partner_id':fields.many2one('res.partner','Customer'),
        'partner_cabang': fields.many2one('dym.cabang.partner',string='Customer Branch'),
        'keterangan':fields.char('Keterangan'),
        'tanggal':fields.date('Tanggal'),
        'penyerahan_line' : fields.one2many('dym.penyerahan.bpkb.line','penyerahan_id',string="Penyerahan STNK"),  
        'state': fields.selection([('draft', 'Draft'), ('posted','Posted'),('cancel','Canceled')], 'State', readonly=True),
        'engine_no': fields.related('penyerahan_line', 'name', type='char', string='No Engine'),
        'customer_stnk': fields.related('penyerahan_line', 'customer_stnk', type='many2one', relation='res.partner', string='Customer STNK', help=' Syarat Penyerahan BKPB: \
                                    \n* Semua tagihan harus sudah lunas (termasuk pajak progresif). \
                                    \n* Sudah proses STNK. \
                                    \n* Sudah terima BPKB'),
        'no_bpkb': fields.related('penyerahan_line', 'no_bpkb', type='char', string='No BPKB'),
        'tgl_penyerahan_bpkb' :fields.date('Tgl Penyerahan BPKB'),
        'cetak_ke' : fields.integer('Cetak Ke'),     
        'confirm_uid':fields.many2one('res.users',string="Posted by"),
        'confirm_date':fields.datetime('Posted on'),        
        'total_record' : fields.integer(string='Total Engine', store=True, readonly=True, compute='_amount_all'),
    }
 
    _defaults = {
        'state':'draft',
        'division' : 'Unit',
        'tanggal': fields.date.context_today,
        'tgl_penyerahan_bpkb': fields.date.context_today,
        'cetak_ke' : 0,
        'branch_id': _get_default_branch,
    } 
    
    def post_penyerahan(self,cr,uid,ids,context=None):
        val = self.browse(cr,uid,ids)
        lot_pool = self.pool.get('stock.production.lot') 
        tanggal = datetime.now()
        for x in val.penyerahan_line :
            lot_search = lot_pool.search(cr,uid,[
                ('id','=',x.name.id)
                ])
            lot_browse = lot_pool.browse(cr,uid,lot_search)
            lot_browse.write({
                   'tgl_penyerahan_bpkb':x.tgl_ambil_bpkb,
                   'lokasi_bpkb_id':False,
                   })   
        self.write(cr, uid, ids, {'state': 'posted','tanggal':tanggal,'confirm_uid':uid,'confirm_date':datetime.now()})       
        return True
    
    def create(self, cr, uid, vals, context=None):
        # if not vals['penyerahan_line'] :
        #     raise osv.except_osv(('Perhatian !'), ("Tidak ada detail penyerahan. Data tidak bisa di save."))
        lot_penyerahan = []
        for x in vals['penyerahan_line']:
            lot_penyerahan.append(x.pop(2))
        lot_pool = self.pool.get('stock.production.lot')
        penyerahan_pool = self.pool.get('dym.penyerahan.bpkb.line')
        vals['name'] = self.pool.get('ir.sequence').get_per_branch(cr, uid, vals['branch_id'], 'PBK', division='Unit')
        
        vals['tanggal'] = time.strftime('%Y-%m-%d'),
        del[vals['penyerahan_line']]

        
        penyerahan_id = super(dym_penyerahan_bpkb, self).create(cr, uid, vals, context=context) 

        if penyerahan_id :         
            for x in lot_penyerahan :
                lot_search = lot_pool.search(cr,uid,[
                            ('id','=',x['name'])
                            ])
                if not lot_search :
                    raise osv.except_osv(('Perhatian !'), ("No Engine tidak ditemukan !"))
                lot_browse = lot_pool.browse(cr,uid,lot_search)
                lot_browse.write({
                       'penyerahan_bpkb_id':penyerahan_id,
                       })   
                penyerahan_pool.create(cr, uid, {
                    'name':lot_browse.id,
                    'penyerahan_id':penyerahan_id,
                    'customer_stnk':lot_browse.customer_stnk.id,
                    'no_bpkb':lot_browse.no_bpkb,
                    'no_urut':lot_browse.no_urut_bpkb,
                    'tgl_ambil_bpkb':x['tgl_ambil_bpkb']
                })
                           
        else :
            return False
        return penyerahan_id

    def write(self, cr, uid, ids, vals, context=None):
        if context is None:
            context = {}
        vals.get('penyerahan_line',[]).sort(reverse=True)

        collect = self.browse(cr,uid,ids)
        lot_penyerahan = []
        lot_pool = self.pool.get('stock.production.lot')
        line_pool = self.pool.get('dym.penyerahan.bpkb.line')
        lot = vals.get('penyerahan_line', False)
        if lot :
            for x,item in enumerate(lot) :
                lot_id = item[1]
                if item[0] == 2 :               
                    line_search = line_pool.search(cr,uid,[
                                                           ('id','=',lot_id)
                                                           ])
                    line_browse = line_pool.browse(cr,uid,line_search)
                    lot_search = lot_pool.search(cr,uid,[
                                           ('id','=',line_browse.name.id)
                                           ])
                    if not line_search :
                        raise osv.except_osv(('Perhatian !'), ("Nomor Engine tidak ada didalam daftar Penerimaan Line"))
                    if not lot_search :
                        raise osv.except_osv(('Perhatian !'), ("Nomor Engine tidak ada didalam daftar Engine Nomor"))
                    lot_browse = lot_pool.browse(cr,uid,lot_search)
                    # del[vals['penyerahan_line']]
                    lot_browse.write({
                                   'penyerahan_bpkb_id':False,
                                   'tgl_penyerahan_bpkb':False
                                     })
                    # line_pool.unlink(cr,uid,lot_id, context=context)
                        
                elif item[0] == 0 :
                    values = item[2]
                    lot_search = lot_pool.search(cr,uid,[
                                                        ('id','=',values['name'])
                                                        ])
                    if not lot_search :
                        raise osv.except_osv(('Perhatian !'), ("Nomor Engine tidak ada didalam daftar Engine Nomor"))
                    
                    lot_browse = lot_pool.browse(cr,uid,lot_search)
                    lot_browse.write({
                           'penyerahan_bpkb_id':collect.id,
                           }) 
                    
        return super(dym_penyerahan_bpkb, self).write(cr, uid, ids, vals, context=context) 

    def unlink(self, cr, uid, ids, context=None):
        for item in self.browse(cr, uid, ids, context=context):
            if item.state != 'draft':
                raise osv.except_osv(('Perhatian !'), ("Penyerahan BPKB sudah di post ! tidak bisa didelete !"))

        lot_pool = self.pool.get('stock.production.lot')
        lot_search = lot_pool.search(cr,uid,[
                                           ('penyerahan_bpkb_id','=',ids)
                                           ])
        lot_browse = lot_pool.browse(cr,uid,lot_search)
        for x in lot_browse :
            x.write({
                     'tgl_penyerahan_bpkb':False,
                     })
        return super(dym_penyerahan_bpkb, self).unlink(cr, uid, ids, context=context)   
    
    def onchange_partner(self,cr,uid,ids,partner,penerima,context=None):
        warning = {}  
        value = {}  
        result = {}

        obj_browse = self.pool.get('res.partner').browse(cr,uid,[partner]) 


        if partner:
            res_partner = self.pool.get('res.partner').search(cr,uid,[
                                                                      ('id','=',partner)
                                                                      ])
            res_partner_browse = self.pool.get('res.partner').browse(cr,uid,res_partner)            
            if obj_browse.finance_company :
                value = {'penerima':res_partner_browse.name}
        if partner and penerima :
            if obj_browse.finance_company and penerima != obj_browse.name:
                warning = {
                        'title': ('Perhatian !'),
                        'message': ('A/N BPKB adalah Finance Company, Nama Penerima harus sama'),
                    } 
                if warning :
                    value = {'penerima':False}

        result['value'] = value         
        result['warning'] = warning
        return result

    def onchange_branch(self, cr, uid, ids, branch_id, context=None):
        warning = {}  
        domain = {}  
        value = {}  
        result = {}  
        if branch_id:
            branch = self.pool.get('dym.branch').browse(cr,uid,[branch_id])
            domain_lot = ['&','&','&','&',('tgl_proses_birojasa','!=',False),('tgl_terima_bpkb','!=',False),('state_stnk','=','proses_stnk'),('branch_id','=',branch_id),('tgl_penyerahan_bpkb','=',False),'|',('finco_id','!=',False),'&',('customer_id','!=',False),('finco_id','=',False)]
            lot_ids = self.pool.get('stock.production.lot').search(cr, uid, domain_lot)
            lot = self.pool.get('stock.production.lot').browse(cr, uid, lot_ids)
            finco = lot.mapped('finco_id')
            partner = lot.filtered(lambda r: not r.finco_id).mapped('customer_id')
            domain['partner_id'] = ['|',('id','in',finco.ids),('id','in',partner.ids)]
        result['domain'] = domain       
        result['value'] = value         
        result['warning'] = warning
        return result
Exemplo n.º 54
0
                        raise orm.except_orm('Error', 'Failure creating the'
                            ' account move lines.')
                else:
                    logging.getLogger(self._name).info("Este activo ya esta asentado!")

    _columns = {
        'asset_code': fields.char('Codigo', size=32, required=False, readonly=False),
        'category_id': fields.many2one('account.asset.category', 'Asset Category', required=True,
                                       change_default=True, readonly=True, states={'draft':[('readonly',False)]},
                                       domain=[('type','=','normal')]),
        'category_parent_id': fields.many2one("account.asset.category", string="Categoria Padre del Activo",
                                              required=False, readonly=True, states={'draft':[('readonly',False)]},
                                              domain=[('type','=','view')] ),
        'account_analytic_id': fields.many2one("account.analytic.account", string="Cuenta analitica",
                                               required=True, domain=[('type','=','normal')]),
        'asset_move_ids': fields.one2many('account.asset.move', 'asset_id','Movimientos'),

        #'asset_move_ids': fields.one2many('account.asset.move', 'asset_id', 'Movements')
    }

    _defaults = {
        'asset_code': lambda obj, cr, uid, context: obj.pool.get('ir.sequence').get(cr, uid, 'asset.number')
    }


class AssetMove(orm.Model):

    _name = 'account.asset.move'
    _description = 'Movimiento de Activo Fijo'

    READONLY_STATES = {
Exemplo n.º 55
0
class ResUser(orm.Model):
    _inherit = 'res.users'

    _columns = {
        'user_profile':
        fields.boolean('Is User Profile'),
        'user_profile_id':
        fields.many2one('res.users',
                        'User Profile',
                        domain=[('user_profile', '=', True)],
                        context={'active_test': False}),
        'user_ids':
        fields.one2many('res.users',
                        'user_profile_id',
                        'Users',
                        domain=[('user_profile', '=', False)]),
        'field_ids':
        fields.many2many('ir.model.fields',
                         'res_users_fields_rel',
                         'user_id',
                         'field_id',
                         'Fields to update',
                         domain=[('model', 'in', ('res.users', 'res.partner')),
                                 ('name', 'not in',
                                  ('user_profile', 'user_profile_id',
                                   'user_ids', 'field_ids'))]),
    }

    def _get_default_field_ids(self, cr, uid, ids, context=None):
        return self.pool.get('ir.model.fields').search(
            cr,
            uid, [
                ('model', 'in', ('res.users', 'res.partner')),
                ('name', 'in', ('action_id', 'menu_id', 'groups_id')),
            ],
            context=context)

    _defaults = {
        'field_ids': _get_default_field_ids,
    }

    _sql_constraints = [
        ('active_admin_check', 'CHECK (id = 1 AND active = TRUE OR id <> 1)',
         'The user with id = 1 must be always active!'),
        ('profile_without_profile_id',
         'CHECK( (user_profile = TRUE AND user_profile_id IS NULL) OR user_profile = FALSE )',
         'Profile users cannot be linked to a profile!'),
    ]

    def onchange_user_profile(self, cr, uid, ids, user_profile):
        if user_profile:
            return {
                'value': {
                    'active': ids == [1] and True or False,
                    'user_profile_id': False
                }
            }
        return {}

    def _get_user_vals_from_profile(self,
                                    cr,
                                    uid,
                                    user_profile_id,
                                    context=None):
        vals = {}
        user_profile = self.read(cr, uid, user_profile_id)
        for field in self.pool.get('ir.model.fields').read(
                cr, uid, user_profile['field_ids'], ['name']):
            value = user_profile[field['name']]
            if isinstance(value, tuple):
                value = value[0]
            if isinstance(value, list):
                value = [(6, 0, value)]
            vals[field['name']] = value
        vals['user_ids'] = [(5, 0)]
        return vals

    def create(self, cr, uid, vals, context=None):
        if vals.get('user_profile_id'):
            vals.update(
                self._get_user_vals_from_profile(cr, uid,
                                                 vals['user_profile_id'],
                                                 context))
        return super(ResUser, self).create(cr, uid, vals, context)

    def write(self, cr, uid, ids, vals, context=None):
        if isinstance(ids, (int, long)):
            ids = [ids]
        if vals.get('user_profile_id'):
            new_profile_user_ids = []
            same_profile_user_ids = []
            for user in self.read(cr, uid, ids,
                                  ['user_profile', 'user_profile_id'], context,
                                  '_classic_write'):
                if user['user_profile']:
                    raise orm.except_orm(
                        _('Warning!'),
                        _('You cannot change the profile of a user which is itself a profile!'
                          ))
                if user['user_profile_id'] == vals['user_profile_id']:
                    same_profile_user_ids.append(user['id'])
                else:
                    new_profile_user_ids.append(user['id'])
            if same_profile_user_ids:
                super(ResUser, self).write(cr, uid, same_profile_user_ids,
                                           vals, context)
            if new_profile_user_ids:
                vals.update(
                    self._get_user_vals_from_profile(cr, uid,
                                                     vals['user_profile_id'],
                                                     context))
                super(ResUser, self).write(cr, uid, new_profile_user_ids, vals,
                                           context)
        else:
            super(ResUser, self).write(cr, uid, ids, vals, context)
            for user_profile in self.browse(cr, uid, ids, context):
                if user_profile.user_profile and user_profile.user_ids and any(
                        field.name in vals
                        for field in user_profile.field_ids):
                    profile_vals = self._get_user_vals_from_profile(
                        cr, uid, user_profile.id, context)
                    self.write(cr, uid,
                               [user.id for user in user_profile['user_ids']],
                               profile_vals, context)
        return True

    def copy_data(self, cr, uid, user_id, default=None, context=None):
        default = default.copy() if default else {}
        default['user_ids'] = []
        return super(ResUser, self).copy_data(cr, uid, user_id, default,
                                              context)