def _update_models(self, cr, models={}):
     if not models:
         checklist_ids = self.search(cr, 1, [])
         models = dict([(checklist['model_id'][0], {'checklist_id': checklist['id'], 'active_field': checklist['active_field']})
                        for checklist in self.read(cr, 1, checklist_ids, ['model_id', 'active_field'])])
     for model in self.pool.get('ir.model').read(cr, 1, models.keys(), ['model']):
         if self.pool.get(model['model']):
             model_columns = self.pool.get(model['model'])._columns
             checklist_id = models[model['id']] and models[model['id']].get('checklist_id', False)
             if checklist_id:
                 model_columns.update({
                     'checklist_task_instance_ids': fields.function(self._get_checklist_task_instances, type='one2many',
                                                                    relation='checklist.task.instance', string='Checklist Task Instances',
                                                                    store=False),
                     'total_progress_rate': fields.float('Progress Rate', digits=(16, 2)),
                 })
                 columns_to_add = {'total_progress_rate': 'NUMERIC(16,2)'}
                 if models[model['id']].get('active_field', False):
                     if 'active' not in model_columns or model_columns['active']._type != 'boolean':
                         model_columns.update({'active': fields.boolean('Active')})
                     model_columns.update({'total_progress_rate_mandatory': fields.float('Mandatory Progress Rate', digits=(16, 2))})
                     columns_to_add.update({'active': 'BOOLEAN', 'total_progress_rate_mandatory': 'NUMERIC(16,2)'})
                 for column in columns_to_add:
                     cr.execute("""SELECT c.relname FROM pg_class c, pg_attribute a
                                   WHERE c.relname=%s AND a.attname=%s AND c.oid=a.attrelid""", (model['model'].replace('.', '_'), column))
                     if not cr.rowcount:
                         cr.execute('ALTER TABLE "%s" ADD COLUMN "%s" %s' % (model['model'].replace('.', '_'), column, columns_to_add[column]))
                         cr.commit()
             else:
                 if 'checklist_task_instance_ids' in model_columns:
                     del model_columns['checklist_task_instance_ids']
                 if 'total_progress_rate' in model_columns:
                     del model_columns['total_progress_rate']
     return self._update_checklists_cache(cr)
Example #2
0
    def __init__(self, pool, cr):
        """ Dynamically add columns."""

        super(report_prompt_class, self).__init__(pool, cr)

        for counter in range(0, MAX_PARAMS):
            field_name = PARAM_XXX_STRING_VALUE % counter
            self._columns[field_name] = fields.char('String Value', size=64)
            field_name = PARAM_XXX_BOOLEAN_VALUE % counter
            self._columns[field_name] = fields.boolean('Boolean Value')
            field_name = PARAM_XXX_INTEGER_VALUE % counter
            self._columns[field_name] = fields.integer('Integer Value')
            field_name = PARAM_XXX_NUMBER_VALUE % counter
            self._columns[field_name] = fields.float('Number Value')
            field_name = PARAM_XXX_DATE_VALUE % counter
            self._columns[field_name] = fields.date('Date Value')
            field_name = PARAM_XXX_TIME_VALUE % counter
            self._columns[field_name] = fields.datetime('Time Value')

        self.paramfile = False
Example #3
0
    def __init__(self, pool, cr):
        """ Dynamically add columns."""

        super(report_prompt_class, self).__init__(pool, cr)

        for counter in range(0, MAX_PARAMS):
            field_name = PARAM_XXX_STRING_VALUE % counter
            self._columns[field_name] = fields.char('String Value', size=64)
            field_name = PARAM_XXX_BOOLEAN_VALUE % counter
            self._columns[field_name] = fields.boolean('Boolean Value')
            field_name = PARAM_XXX_INTEGER_VALUE % counter
            self._columns[field_name] = fields.integer('Integer Value')
            field_name = PARAM_XXX_NUMBER_VALUE % counter
            self._columns[field_name] = fields.float('Number Value')
            field_name = PARAM_XXX_DATE_VALUE % counter
            self._columns[field_name] = fields.date('Date Value')
            field_name = PARAM_XXX_TIME_VALUE % counter
            self._columns[field_name] = fields.datetime('Time Value')
            field_name = PARAM_XXX_2M_VALUE % counter
            self._columns[field_name] = fields.function(self._multi_select_values.im_func,
                                                        arg={"entry_num": counter},
                                                        fnct_inv=self._multi_select_values_store.im_func,
                                                        fnct_inv_arg={"entry_num": counter},
                                                        method=False, type='many2many', relation='ir.actions.report.multivalues.promptwizard', string='Multi-Select')
    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
    
    
    def devil_cancel(self, cr, uid, ids, context=None):
        return self.write(cr, uid, ids, {'state': 'cancel'}, context=context)
Example #5
0
class res_company(orm.Model):
    _inherit = "res.company"

    _columns = {
        'date_percentage': fields.float('Date percentage'),
    }
Example #6
0
class product_template(osv.osv):
    _name = 'product.template'
    _inherit = 'product.template'
    
    def _product_available(self, cr, uid, ids, name, arg, context=None):
        res = dict.fromkeys(ids, 0)
        for product in self.browse(cr, uid, ids, context=context):
            res[product.id] = {
                # "reception_count": sum([p.reception_count for p in product.product_variant_ids]),
                # "delivery_count": sum([p.delivery_count for p in product.product_variant_ids]),
                "qty_available": sum([p.qty_available for p in product.product_variant_ids]),
                "virtual_available": sum([p.virtual_available for p in product.product_variant_ids]),
                "incoming_qty": sum([p.incoming_qty for p in product.product_variant_ids]),
                "outgoing_qty": sum([p.outgoing_qty for p in product.product_variant_ids]),
            }
        return res

    def _search_product_quantity(self, cr, uid, obj, name, domain, context):
        prod = self.pool.get("product.product")
        res = []
        for field, operator, value in domain:
            #to prevent sql injections
            assert field in ('qty_available', 'virtual_available', 'incoming_qty', 'outgoing_qty'), 'Invalid domain left operand'
            assert operator in ('<', '>', '=', '<=', '>='), 'Invalid domain operator'
            assert isinstance(value, (float, int)), 'Invalid domain right operand'

            if operator == '=':
                operator = '=='

            product_ids = prod.search(cr, uid, [], context=context)
            ids = []
            if product_ids:
                #TODO: use a query instead of this browse record which is probably making the too much requests, but don't forget
                #the context that can be set with a location, an owner...
                for element in prod.browse(cr, uid, product_ids, context=context):
                    if eval(str(element[field]) + operator + str(value)):
                        ids.append(element.id)
            res.append(('product_variant_ids', 'in', ids))
        return res

    _columns = {
        'type': fields.selection([('product', 'Stockable Product'), ('consu', 'Consumable'), ('service', 'Service')], 'Product Type', required=True, help="Consumable: Will not imply stock management for this product. \nStockable product: Will imply stock management for this product."),
        'property_stock_procurement': fields.property(
            type='many2one',
            relation='stock.location',
            string="Procurement Location",
            domain=[('usage','like','procurement')],
            help="This stock location will be used, instead of the default one, as the source location for stock moves generated by procurements."),
        'property_stock_production': fields.property(
            type='many2one',
            relation='stock.location',
            string="Production Location",
            domain=[('usage','like','production')],
            help="This stock location will be used, instead of the default one, as the source location for stock moves generated by manufacturing orders."),
        'property_stock_inventory': fields.property(
            type='many2one',
            relation='stock.location',
            string="Inventory Location",
            domain=[('usage','like','inventory')],
            help="This stock location will be used, instead of the default one, as the source location for stock moves generated when you do an inventory."),
        'sale_delay': fields.float('Customer Lead Time', help="The average delay in days between the confirmation of the customer order and the delivery of the finished products. It's the time you promise to your customers."),
        'loc_rack': fields.char('Rack', size=16),
        'loc_row': fields.char('Row', size=16),
        'loc_case': fields.char('Case', size=16),
        'track_incoming': fields.boolean('Track Incoming Lots', help="Forces to specify a Serial Number for all moves containing this product and coming from a Supplier Location"),
        'track_outgoing': fields.boolean('Track Outgoing Lots', help="Forces to specify a Serial Number for all moves containing this product and going to a Customer Location"),
        'track_all': fields.boolean('Full Lots Traceability', help="Forces to specify a Serial Number on each and every operation related to this product"),
        
        # sum of product variant qty
        # 'reception_count': fields.function(_product_available, multi='qty_available',
        #     fnct_search=_search_product_quantity, type='float', string='Quantity On Hand'),
        # 'delivery_count': fields.function(_product_available, multi='qty_available',
        #     fnct_search=_search_product_quantity, type='float', string='Quantity On Hand'),
        'qty_available': fields.function(_product_available, multi='qty_available',
            fnct_search=_search_product_quantity, type='float', string='Quantity On Hand'),
        'virtual_available': fields.function(_product_available, multi='qty_available',
            fnct_search=_search_product_quantity, type='float', string='Quantity Available'),
        'incoming_qty': fields.function(_product_available, multi='qty_available',
            fnct_search=_search_product_quantity, type='float', string='Incoming'),
        'outgoing_qty': fields.function(_product_available, multi='qty_available',
            fnct_search=_search_product_quantity, type='float', string='Outgoing'),
        
        'route_ids': fields.many2many('stock.location.route', 'stock_route_product', 'product_id', 'route_id', 'Routes', domain="[('product_selectable', '=', True)]",
                                    help="Depending on the modules installed, this will allow you to define the route of the product: whether it will be bought, manufactured, MTO/MTS,..."),
    }

    _defaults = {
        'sale_delay': 7,
    }

    def action_view_routes(self, cr, uid, ids, context=None):
        route_obj = self.pool.get("stock.location.route")
        act_obj = self.pool.get('ir.actions.act_window')
        mod_obj = self.pool.get('ir.model.data')
        product_route_ids = set()
        for product in self.browse(cr, uid, ids, context=context):
            product_route_ids |= set([r.id for r in product.route_ids])
            product_route_ids |= set([r.id for r in product.categ_id.total_route_ids])
        route_ids = route_obj.search(cr, uid, ['|', ('id', 'in', list(product_route_ids)), ('warehouse_selectable', '=', True)], context=context)
        result = mod_obj.get_object_reference(cr, uid, 'stock', 'action_routes_form')
        id = result and result[1] or False
        result = act_obj.read(cr, uid, [id], context=context)[0]
        result['domain'] = "[('id','in',[" + ','.join(map(str, route_ids)) + "])]"
        return result
Example #7
0
def selection_fn(obj, cr, uid, context=None):
    return list(enumerate(["Corge", "Grault", "Wheee", "Moog"]))

def function_fn(model, cr, uid, ids, field_name, arg, context):
    return dict((id, 3) for id in ids)

def function_fn_write(model, cr, uid, id, field_name, field_value, fnct_inv_arg, context):
    """ just so CreatorCase.export can be used
    """
    pass

models = [
    ('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")),
class report_project_task_user(osv.osv):
    _name = "report.project.task.user"
    _description = "Tasks by user and project"
    _auto = False
    _columns = {
        'name':
        fields.char('Task Summary', size=128, readonly=True),
        'day':
        fields.char('Day', size=128, readonly=True),
        'year':
        fields.char('Year', size=64, required=False, readonly=True),
        'user_id':
        fields.many2one('res.users', 'Assigned To', readonly=True),
        'date_start':
        fields.date('Starting Date', readonly=True),
        'no_of_days':
        fields.integer('# of Days', size=128, readonly=True),
        'date_end':
        fields.date('Ending Date', readonly=True),
        'date_deadline':
        fields.date('Deadline', readonly=True),
        'project_id':
        fields.many2one('project.project', 'Project', readonly=True),
        'hours_planned':
        fields.float('Planned Hours', readonly=True),
        'hours_effective':
        fields.float('Effective Hours', readonly=True),
        'hours_delay':
        fields.float('Avg. Plan.-Eff.', readonly=True),
        'remaining_hours':
        fields.float('Remaining Hours', readonly=True),
        'progress':
        fields.float('Progress', readonly=True, group_operator='avg'),
        'total_hours':
        fields.float('Total Hours', readonly=True),
        'closing_days':
        fields.float('Days to Close',
                     digits=(16, 2),
                     readonly=True,
                     group_operator="avg",
                     help="Number of Days to close the task"),
        'opening_days':
        fields.float('Days to Open',
                     digits=(16, 2),
                     readonly=True,
                     group_operator="avg",
                     help="Number of Days to Open the task"),
        'delay_endings_days':
        fields.float('Overpassed Deadline', digits=(16, 2), readonly=True),
        'nbr':
        fields.integer('# of tasks', readonly=True),
        'priority':
        fields.selection([('4', 'Very Low'), ('3', 'Low'), ('2', 'Medium'),
                          ('1', 'Urgent'), ('0', 'Very urgent')],
                         'Priority',
                         readonly=True),
        'month':
        fields.selection([('01', 'January'), ('02', 'February'),
                          ('03', 'March'), ('04', 'April'), ('05', 'May'),
                          ('06', 'June'), ('07', 'July'), ('08', 'August'),
                          ('09', 'September'), ('10', 'October'),
                          ('11', 'November'), ('12', 'December')],
                         'Month',
                         readonly=True),
        'state':
        fields.selection([('draft', 'Draft'), ('open', 'In Progress'),
                          ('pending', 'Pending'), ('cancelled', 'Cancelled'),
                          ('done', 'Done')],
                         'Status',
                         readonly=True),
        'company_id':
        fields.many2one('res.company', 'Company', readonly=True),
        'partner_id':
        fields.many2one('res.partner', 'Contact', readonly=True),
    }
    _order = 'name desc, project_id'

    def init(self, cr):
        tools.sql.drop_view_if_exists(cr, 'report_project_task_user')
        cr.execute("""
            CREATE view report_project_task_user as
              SELECT
                    (select 1 ) AS nbr,
                    t.id as id,
                    to_char(date_start, 'YYYY') as year,
                    to_char(date_start, 'MM') as month,
                    to_char(date_start, 'YYYY-MM-DD') as day,
                    date_trunc('day',t.date_start) as date_start,
                    date_trunc('day',t.date_end) as date_end,
                    to_date(to_char(t.date_deadline, 'dd-MM-YYYY'),'dd-MM-YYYY') as date_deadline,
--                    sum(cast(to_char(date_trunc('day',t.date_end) - date_trunc('day',t.date_start),'DD') as int)) as no_of_days,
                    abs((extract('epoch' from (t.date_end-t.date_start)))/(3600*24))  as no_of_days,
                    t.user_id,
                    progress as progress,
                    t.project_id,
                    t.state,
                    t.effective_hours as hours_effective,
                    t.priority,
                    t.name as name,
                    t.company_id,
                    t.partner_id,
                    t.stage_id,
                    remaining_hours as remaining_hours,
                    total_hours as total_hours,
                    t.delay_hours as hours_delay,
                    planned_hours as hours_planned,
                    (extract('epoch' from (t.date_end-t.create_date)))/(3600*24)  as closing_days,
                    (extract('epoch' from (t.date_start-t.create_date)))/(3600*24)  as opening_days,
                    abs((extract('epoch' from (t.date_deadline-t.date_end)))/(3600*24))  as delay_endings_days
              FROM project_task t
                WHERE t.active = 'true'
                GROUP BY
                    t.id,
                    remaining_hours,
                    t.effective_hours,
                    progress,
                    total_hours,
                    planned_hours,
                    hours_delay,
                    year,
                    month,
                    day,
                    create_date,
                    date_start,
                    date_end,
                    date_deadline,
                    t.user_id,
                    t.project_id,
                    t.state,
                    t.priority,
                    name,
                    t.company_id,
                    t.partner_id,
                    t.stage_id

        """)
# You should have received a copy of the GNU Affero General Public License     #
# along with this program.  If not, see <http://www.gnu.org/licenses/>.        #
###############################################################################

import time

from openerp.osv import orm, fields
from openerp.addons import decimal_precision as dp
from .res_company import COMPANY_FISCAL_TYPE, COMPANY_FISCAL_TYPE_DEFAULT

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"),
}
Example #10
0
									WHERE rel.invoice_id = ANY(%s)""", (list(ids),))
		return [i[0] for i in cr.fetchall()]

	_name = 'sale.order.line'
	_description = 'Sales Order Line'
	_columns = {
		'order_id': fields.many2one('sale.order', 'Order Reference', required=True, ondelete='cascade', select=True, readonly=True, states={'draft':[('readonly',False)]}),
		'name': fields.text('Description', required=True, readonly=True, states={'draft': [('readonly', False)]}),
		'sequence': fields.integer('Sequence', help="Gives the sequence order when displaying a list of sales order lines."),
		'product_id': fields.many2one('product.product', 'Product', domain=[('sale_ok', '=', True)], change_default=True),
		'invoice_lines': fields.many2many('account.invoice.line', 'sale_order_line_invoice_rel', 'order_line_id', 'invoice_id', 'Invoice Lines', readonly=True),
		'invoiced': fields.function(_fnct_line_invoiced, string='Invoiced', type='boolean',
			store={
				'account.invoice': (_order_lines_from_invoice, ['state'], 10),
				'sale.order.line': (lambda self,cr,uid,ids,ctx=None: ids, ['invoice_lines'], 10)}),
		'price_unit': fields.float('Unit Price', required=True, digits_compute= dp.get_precision('Product Price'), readonly=True, states={'draft': [('readonly', False)]}),
		'type': fields.selection([('make_to_stock', 'from stock'), ('make_to_order', 'on order')], 'Procurement Method', required=True, readonly=True, states={'draft': [('readonly', False)]},
		 help="From stock: When needed, the product is taken from the stock or we wait for replenishment.\nOn order: When needed, the product is purchased or produced."),
		'price_subtotal': fields.function(_amount_line, string='Subtotal', digits_compute= dp.get_precision('Account')),
		'tax_id': fields.many2many('account.tax', 'sale_order_tax', 'order_line_id', 'tax_id', 'Taxes', readonly=True, states={'draft': [('readonly', False)]}),
		'address_allotment_id': fields.many2one('res.partner', 'Allotment Partner',help="A partner to whom the particular product needs to be allotted."),
		'product_uom_qty': fields.float('Quantity', digits_compute= dp.get_precision('Product UoS'), 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'),
		'discount': fields.float('Discount (%)', digits_compute= dp.get_precision('Discount'), readonly=True, states={'draft': [('readonly', False)]}),
		'th_weight': fields.float('Weight', readonly=True, states={'draft': [('readonly', False)]}),
		'state': fields.selection([('cancel', 'Cancelled'),('draft', 'Draft'),('confirmed', 'Confirmed'),('exception', 'Exception'),('done', 'Done')], 'Status', required=True, readonly=True,
				help='* The \'Draft\' status is set when the related sales order in draft status. \
					\n* The \'Confirmed\' status is set when the related sales order is confirmed. \
					\n* The \'Exception\' status is set when the related sales order is set as exception. \
Example #11
0
class account_bank_statement(osv.osv):
    def create(self, cr, uid, vals, context=None):
        if vals.get('name', '/') == '/':
            journal_id = vals.get('journal_id', self._default_journal_id(cr, uid, context=context))
            vals['name'] = self._compute_default_statement_name(cr, uid, journal_id, context=context)
        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 _compute_default_statement_name(self, cr, uid, journal_id, context=None):
        if context is None:
            context = {}
        obj_seq = self.pool.get('ir.sequence')
        period = self.pool.get('account.period').browse(cr, uid, self._get_period(cr, uid, context=context), context=context)
        context['fiscalyear_id'] = period.fiscalyear_id.id
        journal = self.pool.get('account.journal').browse(cr, uid, journal_id, None)
        return obj_seq.next_by_id(cr, uid, journal.sequence_id.id, context=context)

    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()

    def _all_lines_reconciled(self, cr, uid, ids, name, args, context=None):
        res = {}
        for statement in self.browse(cr, uid, ids, context=context):
            res[statement.id] = all([line.journal_entry_id.id for line in statement.line_ids])
        return res

    _order = "date desc, id desc"
    _name = "account.bank.statement"
    _description = "Bank Statement"
    _inherit = ['mail.thread']
    _columns = {
        'name': fields.char('Reference', size=64, 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)]}, help="Computed using the cash control lines"),
        '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 Opening 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.'),
        'cash_control': fields.related('journal_id', 'cash_control' , type='boolean', relation='account.journal',string='Cash control'),
        'all_lines_reconciled': fields.function(_all_lines_reconciled, string='All lines reconciled', type='boolean'),
    }

    _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 _get_counter_part_account(sefl, cr, uid, st_line, context=None):
        """Retrieve the account to use in the counterpart move.

           :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.

           :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_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 counter part move line from a
           statement line by calling the _prepare_move_line_vals. 

           :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
        """
        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.currency_id or st_line.statement_id.currency.id
        if st_line.currency_id and st_line.amount_currency:
            amt_cur = st_line.amount_currency
            cur_id = st_line.currency_id.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, partner_id=False, context=None):
        """Prepare the dict of values to create the move line from a
           statement line.

           :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 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,
        }

    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):
        if context is None:
            context = {}

        for st in self.browse(cr, uid, ids, context=context):
            j_type = st.journal_id.type
            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.'))
            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.'))
            move_ids = []
            for st_line in st.line_ids:
                if not st_line.amount:
                    continue
                if not st_line.journal_entry_id.id:
                    raise osv.except_osv(_('Error!'), _('All the account entries lines must be processed in order to close the statement.'))
                move_ids.append(st_line.journal_entry_id.id)
            self.pool.get('account.move').post(cr, uid, move_ids, context=context)
            self.message_post(cr, uid, [st.id], body=_('Statement %s confirmed, journal items were created.') % (st.name,), context=context)
        self.link_bank_to_partner(cr, uid, ids, context=context)
        return self.write(cr, uid, ids, {'state':'confirm'}, context=context)

    def button_cancel(self, cr, uid, ids, context=None):
        account_move_obj = self.pool.get('account.move')
        reconcile_pool = self.pool.get('account.move.reconcile')
        move_line_pool = self.pool.get('account.move.line')
        move_ids = []
        for st in self.browse(cr, uid, ids, context=context):
            for line in st.line_ids:
                if line.journal_entry_id:
                    move_ids.append(line.journal_entry_id.id)
                    for aml in line.journal_entry_id.line_id:
                        if aml.reconcile_id:
                            move_lines = [l.id for l in aml.reconcile_id.line_id]
                            move_lines.remove(aml.id)
                            reconcile_pool.unlink(cr, uid, [aml.reconcile_id.id], context=context)
                            if len(move_lines) >= 2:
                                move_line_pool.reconcile_partial(cr, uid, move_lines, 'auto', context=context)
        if move_ids:
            account_move_obj.button_cancel(cr, uid, move_ids, context=context)
            account_move_obj.unlink(cr, uid, move_ids, context)
        return self.write(cr, uid, ids, {'state': 'draft'}, context=context)

    def _compute_balance_end_real(self, cr, uid, journal_id, context=None):
        res = False
        if journal_id:
            journal = self.pool.get('account.journal').browse(cr, uid, journal_id, context=context)
            if journal.with_last_closing_balance:
                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 = self.pool.get('account.journal').browse(cr, uid, journal_id, context=context)
        currency = journal.currency or journal.company_id.currency_id
        res = {'balance_start': balance_start, 'company_id': journal.company_id.id, 'currency': currency.id}
        if journal.type == 'cash':
            res['cash_control'] = journal.cash_control
        return {'value': res}

    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 {
            'name': _('Journal Items'),
            '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,
        }

    def number_of_lines_reconciled(self, cr, uid, id, context=None):
        bsl_obj = self.pool.get('account.bank.statement.line')
        return bsl_obj.search_count(cr, uid, [('statement_id', '=', id), ('journal_entry_id', '!=', False)], context=context)
        
    def get_format_currency_js_function(self, cr, uid, id, context=None):
        """ Returns a string that can be used to instanciate a javascript function.
            That function formats a number according to the statement line's currency or the statement currency"""
        company_currency = self.pool.get('res.users').browse(cr, uid, uid, context=context).company_id.currency_id
        st = id and self.browse(cr, uid, id, context=context)
        if not st:
            return
        statement_currency = st.journal_id.currency or company_currency
        digits = 2 # TODO : from currency_obj
        function = ""
        done_currencies = []
        for st_line in st.line_ids:
            st_line_currency = st_line.currency_id or statement_currency
            if st_line_currency.id not in done_currencies:
                if st_line_currency.position == 'after':
                    return_str = "return amount.toFixed(" + str(digits) + ") + ' " + st_line_currency.symbol + "';"
                else:
                    return_str = "return '" + st_line_currency.symbol + " ' + amount.toFixed(" + str(digits) + ");"
                function += "if (currency_id === " + str(st_line_currency.id) + "){ " + return_str + " }"
                done_currencies.append(st_line_currency.id)
        return function

    def link_bank_to_partner(self, cr, uid, ids, context=None):
        for statement in self.browse(cr, uid, ids, context=context):
            for st_line in statement.line_ids:
                if st_line.bank_account_id and st_line.partner_id and st_line.bank_account_id.partner_id.id != st_line.partner_id.id:
                    self.pool.get('res.partner.bank').write(cr, uid, [st_line.bank_account_id.id], {'partner_id': st_line.partner_id.id}, context=context)
Example #12
0
class account_bank_statement_line(osv.osv):

    def get_data_for_reconciliations(self, cr, uid, ids, context=None):
        """ Used to instanciate a batch of reconciliations in a single request """
        # Build a list of reconciliations data
        ret = []
        mv_line_ids_selected = []
        for st_line_id in ids:
            reconciliation_data = {
                'st_line': self.get_statement_line_for_reconciliation(cr, uid, st_line_id, context),
                'reconciliation_proposition': self.get_reconciliation_proposition(cr, uid, st_line_id, mv_line_ids_selected, context)
            }
            for mv_line in reconciliation_data['reconciliation_proposition']:
                mv_line_ids_selected.append(mv_line['id'])
            ret.append(reconciliation_data)

        # Check if, now that 'candidate' move lines were selected, there are moves left for statement lines
        #for reconciliation_data in ret:
        #    if not reconciliation_data['st_line']['has_no_partner']:
        #        st_line = self.browse(cr, uid, reconciliation_data['st_line']['id'], context=context)
        #        if not self.get_move_lines_counterparts(cr, uid, st_line, excluded_ids=mv_line_ids_selected, count=True, context=context):
        #            reconciliation_data['st_line']['no_match'] = True
        return ret

    def get_statement_line_for_reconciliation(self, cr, uid, id, context=None):
        """ Returns the data required by the bank statement reconciliation use case """
        line = self.browse(cr, uid, id, context=context)
        statement_currency = line.journal_id.currency or line.journal_id.company_id.currency_id
        amount = line.amount
        rml_parser = report_sxw.rml_parse(cr, uid, 'statement_line_widget', context=context)
        amount_str = line.amount > 0 and line.amount or -line.amount
        amount_str = rml_parser.formatLang(amount_str, currency_obj=statement_currency)
        amount_currency_str = ""
        if line.amount_currency and line.currency_id:
            amount_currency_str = amount_str
            amount_str = rml_parser.formatLang(line.amount_currency, currency_obj=line.currency_id)
            amount = line.amount_currency

        data = {
            'id': line.id,
            'ref': line.ref,
            'note': line.note or "",
            'name': line.name,
            'date': line.date,
            'amount': amount,
            'amount_str': amount_str,
            'currency_id': line.currency_id.id or statement_currency.id,
            'no_match': self.get_move_lines_counterparts(cr, uid, line, count=True, context=context) == 0,
            'partner_id': line.partner_id.id,
            'statement_id': line.statement_id.id,
            'account_code': line.journal_id.default_debit_account_id.code,
            'account_name': line.journal_id.default_debit_account_id.name,
            'partner_name': line.partner_id.name,
            'amount_currency_str': amount_currency_str,
            'has_no_partner': not line.partner_id.id,
        }
        if line.partner_id.id:
            data['open_balance_account_id'] = line.partner_id.property_account_payable.id
            if amount > 0:
                data['open_balance_account_id'] = line.partner_id.property_account_receivable.id
        return data

    def search_structured_com(self, cr, uid, st_line, context=None):
        if not st_line.ref:
            return
        domain = [('ref', '=', st_line.ref)]
        if st_line.partner_id:
            domain += [('partner_id', '=', st_line.partner_id.id)]
        ids = self.pool.get('account.move.line').search(cr, uid, domain, limit=1, context=context)
        return ids and ids[0] or False

    def get_reconciliation_proposition(self, cr, uid, id, excluded_ids=[], context=None):
        """ Returns move lines that constitute the best guess to reconcile a statement line. """
        st_line = self.browse(cr, uid, id, context=context)
        company_currency = st_line.journal_id.company_id.currency_id.id
        statement_currency = st_line.journal_id.currency.id or company_currency
        # either use the unsigned debit/credit fields or the signed amount_currency field
        sign = 1
        if statement_currency == company_currency:
            amount_field = 'credit'
            if st_line.amount > 0:
                amount_field = 'debit'
        else:
            amount_field = 'amount_currency'
            if st_line.amount < 0:
                sign = -1

        # look for structured communication
        exact_match_id = self.search_structured_com(cr, uid, st_line, context=context)
        if exact_match_id:
            return self.make_counter_part_lines(cr, uid, st_line, [exact_match_id], count=False, context=context)
        #we don't propose anything if there is no partner detected
        if not st_line.partner_id.id:
            return []
        # look for exact match
        exact_match_id = self.get_move_lines_counterparts(cr, uid, st_line, excluded_ids=excluded_ids, limit=1, additional_domain=[(amount_field, '=', (sign * st_line.amount))])
        if exact_match_id:
            return exact_match_id

        # select oldest move lines
        if sign == -1:
            mv_lines = self.get_move_lines_counterparts(cr, uid, st_line, excluded_ids=excluded_ids, limit=50, additional_domain=[(amount_field, '<', 0)])
        else:
            mv_lines = self.get_move_lines_counterparts(cr, uid, st_line, excluded_ids=excluded_ids, limit=50, additional_domain=[(amount_field, '>', 0)])
        ret = []
        total = 0
        # get_move_lines_counterparts inverts debit and credit
        amount_field = 'debit' if amount_field == 'credit' else 'credit'
        for line in mv_lines:
            if total + line[amount_field] <= abs(st_line.amount):
                ret.append(line)
                total += line[amount_field]
            if total >= abs(st_line.amount):
                break
        return ret

    def get_move_lines_counterparts_id(self, cr, uid, st_line_id, excluded_ids=[], filter_str="", offset=0, limit=None, count=False, additional_domain=[], context=None):
        st_line = self.browse(cr, uid, st_line_id, context=context)
        return self.get_move_lines_counterparts(cr, uid, st_line, excluded_ids, filter_str, offset, limit, count, additional_domain, context=context)

    def get_move_lines_counterparts(self, cr, uid, st_line, excluded_ids=[], filter_str="", offset=0, limit=None, count=False, additional_domain=[], context=None):
        """ Find the move lines that could be used to reconcile a statement line and returns the counterpart that could be created to reconcile them
            If count is true, only returns the count.

            :param st_line: the browse record of the statement line
            :param integers list excluded_ids: ids of move lines that should not be fetched
            :param string filter_str: string to filter lines
            :param integer offset: offset of the request
            :param integer limit: number of lines to fetch
            :param boolean count: just return the number of records
            :param tuples list domain: additional domain restrictions
        """
        mv_line_pool = self.pool.get('account.move.line')

        domain = additional_domain + [
            ('reconcile_id', '=', False),
            ('state', '=', 'valid'),
        ]
        if st_line.partner_id.id:
            domain += [('partner_id', '=', st_line.partner_id.id),
                '|', ('account_id.type', '=', 'receivable'),
                ('account_id.type', '=', 'payable')]
        else:
            domain += [('account_id.reconcile', '=', True)]
            #domain += [('account_id.reconcile', '=', True), ('account_id.type', '=', 'other')]
        if excluded_ids:
            domain.append(('id', 'not in', excluded_ids))
        if filter_str:
            if not st_line.partner_id:
                domain += [ '|', ('partner_id.name', 'ilike', filter_str)]
            domain += ['|', ('move_id.name', 'ilike', filter_str), ('move_id.ref', 'ilike', filter_str)]
        line_ids = mv_line_pool.search(cr, uid, domain, offset=offset, limit=limit, order="date_maturity asc, id asc", context=context)
        return self.make_counter_part_lines(cr, uid, st_line, line_ids, count=count, context=context)

    def make_counter_part_lines(self, cr, uid, st_line, line_ids, count=False, context=None):
        if context is None:
            context = {}
        mv_line_pool = self.pool.get('account.move.line')
        currency_obj = self.pool.get('res.currency')
        company_currency = st_line.journal_id.company_id.currency_id
        statement_currency = st_line.journal_id.currency or company_currency
        rml_parser = report_sxw.rml_parse(cr, uid, 'statement_line_counterpart_widget', context=context)
        #partially reconciled lines can be displayed only once
        reconcile_partial_ids = []
        if count:
            nb_lines = 0
            for line in mv_line_pool.browse(cr, uid, line_ids, context=context):
                if line.reconcile_partial_id and line.reconcile_partial_id.id in reconcile_partial_ids:
                    continue
                nb_lines += 1
                if line.reconcile_partial_id:
                    reconcile_partial_ids.append(line.reconcile_partial_id.id)
            return nb_lines
        else:
            ret = []
            for line in mv_line_pool.browse(cr, uid, line_ids, context=context):
                if line.reconcile_partial_id and line.reconcile_partial_id.id in reconcile_partial_ids:
                    continue
                amount_currency_str = ""
                if line.currency_id and line.amount_currency:
                    amount_currency_str = rml_parser.formatLang(line.amount_currency, currency_obj=line.currency_id)
                ret_line = {
                    'id': line.id,
                    'name': line.move_id.name,
                    'ref': line.move_id.ref,
                    'account_code': line.account_id.code,
                    'account_name': line.account_id.name,
                    'account_type': line.account_id.type,
                    'date_maturity': line.date_maturity,
                    'date': line.date,
                    'period_name': line.period_id.name,
                    'journal_name': line.journal_id.name,
                    'amount_currency_str': amount_currency_str,
                    'partner_id': line.partner_id.id,
                    'partner_name': line.partner_id.name,
                    'has_no_partner': not bool(st_line.partner_id.id),
                }
                st_line_currency = st_line.currency_id or statement_currency
                if st_line.currency_id and line.currency_id and line.currency_id.id == st_line.currency_id.id:
                    if line.amount_residual_currency < 0:
                        ret_line['debit'] = 0
                        ret_line['credit'] = -line.amount_residual_currency
                    else:
                        ret_line['debit'] = line.amount_residual_currency if line.credit != 0 else 0
                        ret_line['credit'] = line.amount_residual_currency if line.debit != 0 else 0
                    ret_line['amount_currency_str'] = rml_parser.formatLang(line.amount_residual, currency_obj=company_currency)
                else:
                    if line.amount_residual < 0:
                        ret_line['debit'] = 0
                        ret_line['credit'] = -line.amount_residual
                    else:
                        ret_line['debit'] = line.amount_residual if line.credit != 0 else 0
                        ret_line['credit'] = line.amount_residual if line.debit != 0 else 0
                    ctx = context.copy()
                    ctx.update({'date': st_line.date})
                    ret_line['debit'] = currency_obj.compute(cr, uid, st_line_currency.id, company_currency.id, ret_line['debit'], context=ctx)
                    ret_line['credit'] = currency_obj.compute(cr, uid, st_line_currency.id, company_currency.id, ret_line['credit'], context=ctx)
                ret_line['debit_str'] = rml_parser.formatLang(ret_line['debit'], currency_obj=st_line_currency)
                ret_line['credit_str'] = rml_parser.formatLang(ret_line['credit'], currency_obj=st_line_currency)
                ret.append(ret_line)
                if line.reconcile_partial_id:
                    reconcile_partial_ids.append(line.reconcile_partial_id.id)
            return ret

    def get_currency_rate_line(self, cr, uid, st_line, currency_diff, move_id, context=None):
        if currency_diff < 0:
            account_id = st_line.company_id.expense_currency_exchange_account_id.id
            if not account_id:
                raise osv.except_osv(_('Insufficient Configuration!'), _("You should configure the 'Loss Exchange Rate Account' in the accounting settings, to manage automatically the booking of accounting entries related to differences between exchange rates."))
        else:
            account_id = st_line.company_id.income_currency_exchange_account_id.id
            if not account_id:
                raise osv.except_osv(_('Insufficient Configuration!'), _("You should configure the 'Gain Exchange Rate Account' in the accounting settings, to manage automatically the booking of accounting entries related to differences between exchange rates."))
        return {
            'move_id': move_id,
            'name': _('change') + ': ' + (st_line.name or '/'),
            'period_id': st_line.statement_id.period_id.id,
            'journal_id': st_line.journal_id.id,
            'partner_id': st_line.partner_id.id,
            'company_id': st_line.company_id.id,
            'statement_id': st_line.statement_id.id,
            'debit': currency_diff < 0 and -currency_diff or 0,
            'credit': currency_diff > 0 and currency_diff or 0,
            'date': st_line.date,
            'account_id': account_id
            }

    def process_reconciliation(self, cr, uid, id, mv_line_dicts, context=None):
        """ Creates a move line for each item of mv_line_dicts and for the statement line. Reconcile a new move line with its counterpart_move_line_id if specified. Finally, mark the statement line as reconciled by putting the newly created move id in the column journal_entry_id.

            :param int id: id of the bank statement line
            :param list of dicts mv_line_dicts: move lines to create. If counterpart_move_line_id is specified, reconcile with it
        """
        if context is None:
            context = {}
        st_line = self.browse(cr, uid, id, context=context)
        company_currency = st_line.journal_id.company_id.currency_id
        statement_currency = st_line.journal_id.currency or company_currency
        bs_obj = self.pool.get('account.bank.statement')
        am_obj = self.pool.get('account.move')
        aml_obj = self.pool.get('account.move.line')
        currency_obj = self.pool.get('res.currency')

        # Checks
        if st_line.journal_entry_id.id:
            raise osv.except_osv(_('Error!'), _('The bank statement line was already reconciled.'))
        for mv_line_dict in mv_line_dicts:
            for field in ['debit', 'credit', 'amount_currency']:
                if field not in mv_line_dict:
                    mv_line_dict[field] = 0.0
            if mv_line_dict.get('counterpart_move_line_id'):
                mv_line = aml_obj.browse(cr, uid, mv_line_dict.get('counterpart_move_line_id'), context=context)
                if mv_line.reconcile_id:
                    raise osv.except_osv(_('Error!'), _('A selected move line was already reconciled.'))

        # Create the move
        move_name = st_line.statement_id.name + "/" + str(st_line.sequence)
        move_vals = bs_obj._prepare_move(cr, uid, st_line, move_name, context=context)
        move_id = am_obj.create(cr, uid, move_vals, context=context)

        # Create the move line for the statement line
        amount = currency_obj.compute(cr, uid, st_line.statement_id.currency.id, company_currency.id, st_line.amount, context=context)
        bank_st_move_vals = bs_obj._prepare_bank_move_line(cr, uid, st_line, move_id, amount, company_currency.id, context=context)
        aml_obj.create(cr, uid, bank_st_move_vals, context=context)
        # Complete the dicts
        st_line_currency = st_line.currency_id or statement_currency
        st_line_currency_rate = st_line.currency_id and statement_currency.id == company_currency.id and (st_line.amount_currency / st_line.amount) or False
        to_create = []
        for mv_line_dict in mv_line_dicts:
            mv_line_dict['ref'] = move_name
            mv_line_dict['move_id'] = move_id
            mv_line_dict['period_id'] = st_line.statement_id.period_id.id
            mv_line_dict['journal_id'] = st_line.journal_id.id
            mv_line_dict['company_id'] = st_line.company_id.id
            mv_line_dict['statement_id'] = st_line.statement_id.id
            if mv_line_dict.get('counterpart_move_line_id'):
                mv_line = aml_obj.browse(cr, uid, mv_line_dict['counterpart_move_line_id'], context=context)
                mv_line_dict['account_id'] = mv_line.account_id.id
            if st_line_currency.id != company_currency.id:
                mv_line_dict['amount_currency'] = mv_line_dict['debit'] - mv_line_dict['credit']
                mv_line_dict['currency_id'] = st_line_currency.id
                if st_line.currency_id and statement_currency.id == company_currency.id and st_line_currency_rate:
                    debit_at_current_rate = self.pool.get('res.currency').round(cr, uid, company_currency, mv_line_dict['debit'] / st_line_currency_rate)
                    credit_at_current_rate = self.pool.get('res.currency').round(cr, uid, company_currency, mv_line_dict['credit'] / st_line_currency_rate)
                else:
                    debit_at_current_rate = currency_obj.compute(cr, uid, st_line_currency.id, company_currency.id, mv_line_dict['debit'], context=context)
                    credit_at_current_rate = currency_obj.compute(cr, uid, st_line_currency.id, company_currency.id, mv_line_dict['credit'], context=context)
                if mv_line_dict.get('counterpart_move_line_id'):
                    #post an account line that use the same currency rate than the counterpart (to balance the account) and post the difference in another line
                    ctx = context.copy()
                    ctx['date'] = mv_line.date
                    debit_at_old_rate = currency_obj.compute(cr, uid, st_line_currency.id, company_currency.id, mv_line_dict['debit'], context=ctx)
                    credit_at_old_rate = currency_obj.compute(cr, uid, st_line_currency.id, company_currency.id, mv_line_dict['credit'], context=ctx)
                    mv_line_dict['credit'] = credit_at_old_rate
                    mv_line_dict['debit'] = debit_at_old_rate
                    if debit_at_old_rate - debit_at_current_rate:
                        currency_diff = debit_at_current_rate - debit_at_old_rate
                        to_create.append(self.get_currency_rate_line(cr, uid, st_line, currency_diff, move_id, context=context))
                    if credit_at_old_rate - credit_at_current_rate:
                        currency_diff = credit_at_current_rate - credit_at_old_rate
                        to_create.append(self.get_currency_rate_line(cr, uid, st_line, currency_diff, move_id, context=context))
                else:
                    mv_line_dict['debit'] = debit_at_current_rate
                    mv_line_dict['credit'] = credit_at_current_rate
            to_create.append(mv_line_dict)
        # Create move lines
        move_line_pairs_to_reconcile = []
        for mv_line_dict in to_create:
            counterpart_move_line_id = None # NB : this attribute is irrelevant for aml_obj.create() and needs to be removed from the dict
            if mv_line_dict.get('counterpart_move_line_id'):
                counterpart_move_line_id = mv_line_dict['counterpart_move_line_id']
                del mv_line_dict['counterpart_move_line_id']
            new_aml_id = aml_obj.create(cr, uid, mv_line_dict, context=context)
            if counterpart_move_line_id != None:
                move_line_pairs_to_reconcile.append([new_aml_id, counterpart_move_line_id])

        # Reconcile
        for pair in move_line_pairs_to_reconcile:
            # TODO : too slow
            aml_obj.reconcile_partial(cr, uid, pair, context=context)

        # Mark the statement line as reconciled
        self.write(cr, uid, id, {'journal_entry_id': move_id}, context=context)

    # FIXME : if it wasn't for the multicompany security settings in account_security.xml, the method would just
    # return [('journal_entry_id', '=', False)]
    # Unfortunately, that spawns a "no access rights" error ; it shouldn't.
    def _needaction_domain_get(self, cr, uid, context=None):
        user = self.pool.get("res.users").browse(cr, uid, uid)
        return ['|',('company_id','=',False),('company_id','child_of',[user.company_id.id]),('journal_entry_id', '=', False)]

    _order = "statement_id desc, sequence"
    _name = "account.bank.statement.line"
    _description = "Bank Statement Line"
    _inherit = ['ir.needaction_mixin']
    _columns = {
        'name': fields.char('Description', required=True),
        'date': fields.date('Date', required=True),
        'amount': fields.float('Amount', digits_compute=dp.get_precision('Account')),
        'partner_id': fields.many2one('res.partner', 'Partner'),
        'bank_account_id': fields.many2one('res.partner.bank','Bank Account'),
        'statement_id': fields.many2one('account.bank.statement', 'Statement', select=True, required=True, ondelete='cascade'),
        'journal_id': fields.related('statement_id', 'journal_id', type='many2one', relation='account.journal', string='Journal', store=True, readonly=True),
        'ref': fields.char('Structured Communication'),
        'note': fields.text('Notes'),
        'sequence': fields.integer('Sequence', select=True, help="Gives the sequence order when displaying a list of bank statement lines."),
        'company_id': fields.related('statement_id', 'company_id', type='many2one', relation='res.company', string='Company', store=True, readonly=True),
        'journal_entry_id': fields.many2one('account.move', 'Journal Entry'),
        'amount_currency': fields.float('Amount Currency', help="The amount expressed in an optional other currency if it is a multi-currency entry.", digits_compute=dp.get_precision('Account')),
        'currency_id': fields.many2one('res.currency', 'Currency', help="The optional other currency if it is a multi-currency entry."),
    }
    _defaults = {
        'name': lambda self,cr,uid,context={}: self.pool.get('ir.sequence').get(cr, uid, 'account.bank.statement.line'),
        'date': lambda self,cr,uid,context={}: context.get('date', fields.date.context_today(self,cr,uid,context=context)),
    }
Example #13
0
class crm_lead_report(osv.Model):
    """ CRM Lead Analysis """
    _name = "crm.lead.report"
    _auto = False
    _description = "CRM Lead Analysis"
    _rec_name = 'date_deadline'
    _inherit = ["crm.tracking.mixin"]

    _columns = {
        'date_deadline':
        fields.date('Exp. Closing', readonly=True, help="Expected Closing"),
        'create_date':
        fields.datetime('Creation Date', readonly=True),
        'opening_date':
        fields.datetime('Assignation Date', readonly=True),
        'date_closed':
        fields.datetime('Close Date', readonly=True),
        'date_last_stage_update':
        fields.datetime('Last Stage Update', readonly=True),
        'nbr_cases':
        fields.integer("# of Cases", readonly=True),

        # durations
        'delay_open':
        fields.float('Delay to Assign',
                     digits=(16, 2),
                     readonly=True,
                     group_operator="avg",
                     help="Number of Days to open the case"),
        'delay_close':
        fields.float('Delay to Close',
                     digits=(16, 2),
                     readonly=True,
                     group_operator="avg",
                     help="Number of Days to close the case"),
        'delay_expected':
        fields.float('Overpassed Deadline',
                     digits=(16, 2),
                     readonly=True,
                     group_operator="avg"),
        'user_id':
        fields.many2one('res.users', 'User', readonly=True),
        'team_id':
        fields.many2one('crm.team',
                        'Sales Team',
                        oldname='section_id',
                        readonly=True),
        'country_id':
        fields.many2one('res.country', 'Country', readonly=True),
        'company_id':
        fields.many2one('res.company', 'Company', readonly=True),
        'probability':
        fields.float('Probability',
                     digits=(16, 2),
                     readonly=True,
                     group_operator="avg"),
        'planned_revenue':
        fields.float(
            'Total Revenue', digits=(16, 2),
            readonly=True),  # TDE FIXME master: rename into total_revenue
        'probable_revenue':
        fields.float(
            'Expected Revenue', digits=(16, 2),
            readonly=True),  # TDE FIXME master: rename into expected_revenue
        'stage_id':
        fields.many2one('crm.stage',
                        'Stage',
                        readonly=True,
                        domain="[('team_ids', '=', team_id)]"),
        'partner_id':
        fields.many2one('res.partner', 'Partner', readonly=True),
        'company_id':
        fields.many2one('res.company', 'Company', readonly=True),
        'priority':
        fields.selection(crm.AVAILABLE_PRIORITIES, 'Priority'),
        'type':
        fields.selection(
            [
                ('lead', 'Lead'),
                ('opportunity', 'Opportunity'),
            ],
            'Type',
            help="Type is used to separate Leads and Opportunities"),
    }

    def init(self, cr):
        """
            CRM Lead Report
            @param cr: the current row, from the database cursor
        """
        tools.drop_view_if_exists(cr, 'crm_lead_report')
        cr.execute("""
            CREATE OR REPLACE VIEW crm_lead_report AS (
                SELECT
                    id,
                    c.date_deadline,
                    count(id) as nbr_cases,

                    c.date_open as opening_date,
                    c.date_closed as date_closed,

                    c.date_last_stage_update as date_last_stage_update,

                    c.user_id,
                    c.probability,
                    c.stage_id,
                    c.type,
                    c.company_id,
                    c.priority,
                    c.team_id,
                    c.campaign_id,
                    c.source_id,
                    c.medium_id,
                    c.partner_id,
                    c.country_id,
                    c.planned_revenue as planned_revenue,
                    c.planned_revenue*(c.probability/100) as probable_revenue,
                    c.create_date as create_date,
                    extract('epoch' from (c.date_closed-c.create_date))/(3600*24) as  delay_close,
                    abs(extract('epoch' from (c.date_deadline - c.date_closed))/(3600*24)) as  delay_expected,
                    extract('epoch' from (c.date_open-c.create_date))/(3600*24) as  delay_open
                FROM
                    crm_lead c
                WHERE c.active = 'true'
                GROUP BY c.id
            )""")
Example #14
0
class stock_history(osv.osv):
    _name = 'stock.history'
    _auto = False
    _order = 'date asc'

    def read_group(self,
                   cr,
                   uid,
                   domain,
                   fields,
                   groupby,
                   offset=0,
                   limit=None,
                   context=None,
                   orderby=False,
                   lazy=True):
        res = super(stock_history, self).read_group(cr,
                                                    uid,
                                                    domain,
                                                    fields,
                                                    groupby,
                                                    offset=offset,
                                                    limit=limit,
                                                    context=context,
                                                    orderby=orderby,
                                                    lazy=lazy)
        if context is None:
            context = {}
        date = context.get('history_date', datetime.now())
        if 'inventory_value' in fields:
            group_lines = {}
            for line in res:
                domain = line.get('__domain', [])
                group_lines.setdefault(
                    str(domain), self.search(cr, uid, domain, context=context))
            line_ids = set()
            for ids in group_lines.values():
                for product_id in ids:
                    line_ids.add(product_id)
            line_ids = list(line_ids)
            lines_rec = {}
            if line_ids:
                cr.execute(
                    'SELECT id, product_id, price_unit_on_quant, company_id, quantity FROM stock_history WHERE id in %s',
                    (tuple(line_ids), ))
                lines_rec = cr.dictfetchall()
            lines_dict = dict((line['id'], line) for line in lines_rec)
            product_ids = list(
                set(line_rec['product_id'] for line_rec in lines_rec))
            products_rec = self.pool['product.product'].read(
                cr, uid, product_ids, ['cost_method', 'id'], context=context)
            products_dict = dict(
                (product['id'], product) for product in products_rec)
            cost_method_product_ids = list(
                set(product['id'] for product in products_rec
                    if product['cost_method'] != 'real'))
            histories = []
            if cost_method_product_ids:
                cr.execute(
                    'SELECT DISTINCT ON (product_id, company_id) product_id, company_id, cost FROM product_price_history WHERE product_id in %s AND datetime <= %s ORDER BY product_id, company_id, datetime DESC',
                    (tuple(cost_method_product_ids), date))
                histories = cr.dictfetchall()
            histories_dict = {}
            for history in histories:
                histories_dict[(history['product_id'],
                                history['company_id'])] = history['cost']
            for line in res:
                inv_value = 0.0
                lines = group_lines.get(str(line.get('__domain', [])))
                for line_id in lines:
                    line_rec = lines_dict[line_id]
                    product = products_dict[line_rec['product_id']]
                    if product['cost_method'] == 'real':
                        price = line_rec['price_unit_on_quant']
                    else:
                        price = histories_dict.get(
                            (product['id'], line_rec['company_id']), 0.0)
                    inv_value += price * line_rec['quantity']
                line['inventory_value'] = inv_value
        return res

    def _get_inventory_value(self, cr, uid, ids, name, attr, context=None):
        if context is None:
            context = {}
        date = context.get('history_date')
        product_obj = self.pool.get("product.product")
        res = {}
        for line in self.browse(cr, uid, ids, context=context):
            if line.product_id.cost_method == 'real':
                res[line.id] = line.quantity * line.price_unit_on_quant
            else:
                res[line.id] = line.quantity * product_obj.get_history_price(
                    cr,
                    uid,
                    line.product_id.id,
                    line.company_id.id,
                    date=date,
                    context=context)
        return res

    _columns = {
        'move_id':
        fields.many2one('stock.move', 'Stock Move', required=True),
        'location_id':
        fields.many2one('stock.location', 'Location', required=True),
        'company_id':
        fields.many2one('res.company', 'Company'),
        'product_id':
        fields.many2one('product.product', 'Product', required=True),
        'product_categ_id':
        fields.many2one('product.category', 'Product Category', required=True),
        'quantity':
        fields.float('Product Quantity'),
        'date':
        fields.datetime('Operation Date'),
        'price_unit_on_quant':
        fields.float('Value'),
        'inventory_value':
        fields.function(_get_inventory_value,
                        string="Inventory Value",
                        type='float',
                        readonly=True),
        'source':
        fields.char('Source'),
        'product_template_id':
        fields.many2one('product.template', 'Product Template', required=True),
        'serial_number':
        fields.char('Serial Number', required=True),
    }

    def init(self, cr):
        tools.drop_view_if_exists(cr, 'stock_history')
        cr.execute("""
            CREATE OR REPLACE VIEW stock_history AS (
              SELECT MIN(id) as id,
                move_id,
                location_id,
                company_id,
                product_id,
                product_categ_id,
                product_template_id,
                SUM(quantity) as quantity,
                date,
                price_unit_on_quant,
                source,
                serial_number
                FROM
                ((SELECT
                    stock_move.id::text || '-' || quant.id::text AS id,
                    quant.id AS quant_id,
                    stock_move.id AS move_id,
                    dest_location.id AS location_id,
                    dest_location.company_id AS company_id,
                    stock_move.product_id AS product_id,
                    product_template.id AS product_template_id,
                    product_template.categ_id AS product_categ_id,
                    quant.qty AS quantity,
                    stock_move.date AS date,
                    quant.cost as price_unit_on_quant,
                    stock_move.origin AS source,
                    stock_production_lot.name AS serial_number
                FROM
                    stock_quant as quant
                LEFT JOIN
                    stock_quant_move_rel ON stock_quant_move_rel.quant_id = quant.id
                LEFT JOIN
                    stock_move ON stock_move.id = stock_quant_move_rel.move_id
                LEFT JOIN
                    stock_production_lot ON stock_production_lot.id = quant.lot_id
                LEFT JOIN
                    stock_location dest_location ON stock_move.location_dest_id = dest_location.id
                LEFT JOIN
                    stock_location source_location ON stock_move.location_id = source_location.id
                LEFT JOIN
                    product_product ON product_product.id = stock_move.product_id
                LEFT JOIN
                    product_template ON product_template.id = product_product.product_tmpl_id
                WHERE quant.qty>0 AND stock_move.state = 'done' AND dest_location.usage in ('internal', 'transit')
                AND (
                    (source_location.company_id is null and dest_location.company_id is not null) or
                    (source_location.company_id is not null and dest_location.company_id is null) or
                    source_location.company_id != dest_location.company_id or
                    source_location.usage not in ('internal', 'transit'))
                ) UNION
                (SELECT
                    '-' || stock_move.id::text || '-' || quant.id::text AS id,
                    quant.id AS quant_id,
                    stock_move.id AS move_id,
                    source_location.id AS location_id,
                    source_location.company_id AS company_id,
                    stock_move.product_id AS product_id,
                    product_template.id AS product_template_id,
                    product_template.categ_id AS product_categ_id,
                    - quant.qty AS quantity,
                    stock_move.date AS date,
                    quant.cost as price_unit_on_quant,
                    stock_move.origin AS source,
                    stock_production_lot.name AS serial_number
                FROM
                    stock_quant as quant
                LEFT JOIN
                    stock_quant_move_rel ON stock_quant_move_rel.quant_id = quant.id
                LEFT JOIN
                    stock_move ON stock_move.id = stock_quant_move_rel.move_id
                LEFT JOIN
                    stock_production_lot ON stock_production_lot.id = quant.lot_id
                LEFT JOIN
                    stock_location source_location ON stock_move.location_id = source_location.id
                LEFT JOIN
                    stock_location dest_location ON stock_move.location_dest_id = dest_location.id
                LEFT JOIN
                    product_product ON product_product.id = stock_move.product_id
                LEFT JOIN
                    product_template ON product_template.id = product_product.product_tmpl_id
                WHERE quant.qty>0 AND stock_move.state = 'done' AND source_location.usage in ('internal', 'transit')
                AND (
                    (dest_location.company_id is null and source_location.company_id is not null) or
                    (dest_location.company_id is not null and source_location.company_id is null) or
                    dest_location.company_id != source_location.company_id or
                    dest_location.usage not in ('internal', 'transit'))
                ))
                AS foo
                GROUP BY move_id, location_id, company_id, product_id, product_categ_id, date, price_unit_on_quant, source, product_template_id, serial_number
            )""")
class ProjectCompletionReport(osv.Model):
    """Project Completion Report"""
    _name = "project.completion.report"
    _auto = False
    _description = "Project Completion Report"
    _rec_name = 'activity_name'

    _columns = {
        'id':
        fields.integer('Id', readonly=True),
        'activity_type':
        fields.selection([
            ('task', 'Task'),
            ('issue', 'Issue'),
        ],
                         'Type',
                         readonly=True,
                         help="Type is used to separate Tasks and Issues"),
        'hours':
        fields.float('Time spent',
                     digits=(16, 2),
                     readonly=True,
                     help="Time spent on timesheet"),
        'user_id':
        fields.many2one('res.users', 'User', readonly=True),
        'project_id':
        fields.many2one('project.project', 'Project', readonly=True),
        'project_state':
        fields.char('State', readonly=True, help="Project State"),
        'activity_stage_id':
        fields.many2one('project.task.type',
                        'Stage',
                        readonly=True,
                        help="Activity Stage"),
        'account_id':
        fields.many2one('account.analytic.account',
                        'Analytic account',
                        readonly=True),
        'activity_id':
        fields.char('Activity id', readonly=True, help="Task id or Issue id"),
        'activity_name':
        fields.char('Activity name',
                    readonly=True,
                    help="Task name or Issue name"),
        'planned_hours':
        fields.float('Init. time',
                     digits=(16, 2),
                     readonly=True,
                     help="Initial time"),
        'remaining_hours':
        fields.float('Remain. time',
                     digits=(16, 2),
                     readonly=True,
                     help="Remaining time"),
        'br_id':
        fields.many2one('business.requirement',
                        'Bus. requ.',
                        readonly=True,
                        help="Business requirement"),
        'partner_id':
        fields.many2one('res.partner', 'Customer', readonly=True),
        'project_categ_id':
        fields.many2one('project.project.category',
                        'Project Cat.',
                        readonly=True,
                        help="Project Category"),
    }

    def init(self, cr):
        """ Project Completion Report

            @param cr: the current row, from the database cursor
        """
        tools.drop_view_if_exists(cr, 'project_completion_report')
        cr.execute("""
            CREATE OR REPLACE VIEW project_completion_report AS (
                SELECT
                    row_number() OVER (ORDER BY q.activity_id) AS id, q.*
                FROM
                (
                    (
                        SELECT
                            'task' AS activity_type,
                            SUM(al.unit_amount) AS hours,
                            t.user_id,
                            p.id AS project_id,
                            p.state AS project_state,
                            t.stage_id AS activity_stage_id,
                            a.id AS account_id,
                            t.id AS activity_id,
                            t.name AS activity_name,
                            t.planned_hours,
                            t.remaining_hours,
                            b.id AS br_id,
                            a.partner_id,
                            p.project_categ_id
                        FROM
                            project_project p
                            -- Link with the analytic account
                            INNER JOIN account_analytic_account a
                                ON a.id = p.analytic_account_id
                            -- Link with the task
                            INNER JOIN project_task t ON t.project_id = p.id
                            -- Link with the timesheet
                            LEFT OUTER JOIN project_task_work tw
                                ON tw.task_id = t.id
                            LEFT OUTER JOIN hr_analytic_timesheet ts
                                ON ts.id = tw.hr_analytic_timesheet_id
                            LEFT OUTER JOIN account_analytic_line al
                                ON al.id = ts.line_id
                            -- Link with the BR
                            LEFT OUTER JOIN business_requirement b
                                ON b.linked_project = p.id
                        GROUP BY
                            t.id, p.id, a.id, b.id
                    )
                    UNION
                    (
                        SELECT
                            'issue' AS activity_type,
                            SUM(al.unit_amount) AS hours,
                            i.user_id,
                            p.id AS project_id,
                            p.state AS project_state,
                            i.stage_id AS activity_stage_id,
                            a.id AS account_id,
                            i.id AS activity_id,
                            i.name AS activity_name,
                            NULL AS planned_hours,
                            NULL AS remaining_hours,
                            b.id AS br_id,
                            a.partner_id,
                            p.project_categ_id
                        FROM
                            project_project p
                            -- Link with the analytic account
                            INNER JOIN account_analytic_account a
                                ON a.id = p.analytic_account_id
                            -- Link with the issue
                            INNER JOIN project_issue i ON i.project_id = p.id
                            -- Link with the timesheet
                            LEFT OUTER JOIN hr_analytic_timesheet ts
                                ON ts.issue_id = i.id
                            LEFT OUTER JOIN account_analytic_line al
                                ON al.id = ts.line_id
                            -- Link with the BR
                            LEFT OUTER JOIN business_requirement b
                                ON b.linked_project = p.id
                        GROUP BY
                            i.id, p.id, a.id, b.id
                    )
                ) AS q
            )""")
class purchase_advance_payment_inv(osv.osv_memory):
    _name = "purchase.advance.payment.inv"
    _description = "Purchase Advance Payment Invoice"

    _columns = {
        'line_percent': fields.float(
            'Installment',
            digits_compute=dp.get_precision('Account'),
            help="The % of installment to be used to "
            "calculate the quantity to invoice"),
    }

    _defaults = {
        'amount': 0.0,
    }

    def create_invoices(self, cr, uid, ids, context=None):
        wizard = self.browse(cr, uid, ids[0], context)
        # Additional case, Line Percentage
        if wizard.line_percent:
            # Getting PO Line IDs of this PO
            purchase_obj = self.pool.get('purchase.order')
            purchase_ids = context.get('active_ids', [])
            order = purchase_obj.browse(cr, uid, purchase_ids[0])

            if order.invoiced_rate + wizard.line_percent > 100:
                raise osv.except_osv(
                    _('Warning!'),
                    _('This percentage is too high, '
                      'it make overall invoiced rate exceed 100%!'))

            order_line_ids = []
            for order_line in order.order_line:
                order_line_ids.append(order_line.id)
            # Assign them into active_ids
            context.update({'active_ids': order_line_ids})
            context.update({'line_percent': wizard.line_percent})
            purchase_order_line_make_invoice_obj = self.pool.get(
                'purchase.order.line_invoice')
            res = purchase_order_line_make_invoice_obj.makeInvoices(
                cr, uid, ids, context=context)
            if not context.get('open_invoices', False):
                return {'type': 'ir.actions.act_window_close'}
            return res

        return super(purchase_advance_payment_inv, self).create_invoices(
            cr, uid, ids, context=context)

    def open_invoices(self, cr, uid, ids, invoice_ids, context=None):
        """ open a view on one of the given invoice_ids """
        ir_model_data = self.pool.get('ir.model.data')
        form_res = ir_model_data.get_object_reference(
            cr, uid, 'account', 'invoice_supplier_form')
        form_id = form_res and form_res[1] or False
        tree_res = ir_model_data.get_object_reference(
            cr, uid, 'account', 'invoice_tree')
        tree_id = tree_res and tree_res[1] or False

        return {
            'name': _('Advance Invoice'),
            'view_type': 'form',
            'view_mode': 'form,tree',
            'res_model': 'account.invoice',
            'res_id': invoice_ids[0],
            'view_id': False,
            'views': [(form_id, 'form'), (tree_id, 'tree')],
            'context': "{'type': 'in_invoice'}",
            'type': 'ir.actions.act_window',
        }
Example #17
0
class LoungeOrderInternationalReport(osv.osv):
    _name = "report.lounge.order.international"
    _description = "Lounge Orders International"
    _auto = False
    _order = 'booking_from_date asc'

    _columns = {
        'partner_id':
        fields.many2one('res.partner', 'Customer Name', readonly=True),
        'lounge_reference':
        fields.char(string='Track No', readonly=True),
        'date_order':
        fields.date(string='Order Date', readonly=True),
        'booking_from_date':
        fields.datetime(string='Booking From', readonly=True),
        'booking_to_date':
        fields.datetime(string='Booking To', readonly=True),
        'company_type':
        fields.char(string='Customer Type', readonly=True),
        'flight_type':
        fields.char(string='Flight Type', readonly=True),
        'flight_number':
        fields.char(string='Flight No', readonly=True),
        'service_01':
        fields.char(string='Service 1', readonly=True),
        'service_02':
        fields.char(string='Service 2', readonly=True),
        'service_03':
        fields.char(string='Service 3', readonly=True),
        'payment_method':
        fields.char(string='Type', readonly=True),
        'grandtotal':
        fields.float('Grand Total', readonly=True),
        'payment_name':
        fields.char('Payment', readonly=True),
        'total_pax':
        fields.integer('No.Pax', readonly=True),
    }

    _defaults = {'total_pax': 1}

    def init(self, cr):
        tools.drop_view_if_exists(cr, 'report_lounge_order_international')
        cr.execute("""
            CREATE OR REPLACE VIEW report_lounge_order_international AS (
                SELECT
                    MIN(lo.id) AS id,
                    lo.partner_id AS partner_id,
                    lo.lounge_reference AS lounge_reference,
                    to_char(lo.date_order, 'YYYY-MM-DD') AS date_order,
                    lo.booking_from_date AS booking_from_date,
                    lo.booking_to_date AS booking_to_date,
                    CASE WHEN rp.company_type='company' THEN 'Company' ELSE 'Individual' END AS company_type,
                    CASE WHEN lo.flight_type='international' THEN 'International' ELSE 'Domestic' END AS flight_type,
                    lo.flight_number AS flight_number,
                    lo.service_01 as service_01,
                    lo.service_02 as service_02,
                    lo.service_03 as service_03,
                    CASE WHEN aj.type='cash' THEN 'Cash' ELSE 'Card' END AS payment_method,
                    SUM(absl.amount) as grandtotal,
                    aj.name AS payment_name,
                    lo.total_pax AS total_pax
                FROM
                    lounge_order AS lo
                LEFT JOIN
                    res_partner AS rp ON rp.id = lo.partner_id
                LEFT JOIN
                    account_bank_statement_line AS absl ON absl.lounge_statement_id = lo.id
                LEFT JOIN
                    account_journal AS aj ON aj.id = absl.journal_id
                WHERE
                    lo.state IN ('paid','invoice') AND lo.flight_type = 'international'
                GROUP BY
                    lo.id,rp.id,aj.id
            )
        """)
Example #18
0
	def _qty_all_2(self, cr, uid, ids, field_name, arg, context=None):
		result = {} 
	
		for line in self.browse(cr, uid, ids, context=context):
			qty = line.qty2_2
			uom = line.uom_id.factor_inv
			qty_all = round(qty*uom,3)
			result[line.id] = qty_all
		return result

	_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'),
Example #19
0
class car_maintenance_request(osv.Model):
    _name = "car.maintenance.request"
    _description = 'Car Maintenance Request'

    def create(self, cr, user, vals, context=None):
        """
           Method that creates a new sequence entry as a name for each new car maintenance request.
           @param vals: Dictionary of the entered data
           @return: Super create method
        """
        if ('name' not in vals) or (vals.get('name') == '/'):
            vals['name'] = self.pool.get('ir.sequence').get(
                cr, user, 'car.maintenance.request')
        return super(car_maintenance_request,
                     self).create(cr, user, vals, context)

    def _amount_all(self, cr, uid, ids, field_name, arg, context={}):
        """ 
           Functional field function that calculates the total cost of all faults.
           @param field_name: list contains name of fields that call this method
           @param arg: extra arguement
           @return: Dictionary of values
        """
        res = {}
        for record in self.browse(cr, uid, ids, context=context):
            val = 0.0
            for line in record.faults:
                val += line.price_subtotal
            res[record.id] = val
        return res

    MAINTENANCE_TYPE_SELECTION = [
        ('regular', 'Regular'),
        ('emergency', 'Emergency'),
        ('other', 'Other'),
    ]
    STATE_SELECTION = [
        ('draft', 'Draft'),
        ('confirmed_d', 'Waiting for requesting party manager To approve'),
        ('confirmed_gd', 'Waiting for department manager to confirm '),
        ('approved_of', 'Waiting for admin affairs Service Manager'),
        #    ('approved_of2', 'Waiting for admin affairs Service Manager'),
        ('officer_of', 'Waiting for admin affairs officer'),
        ('confirmed_gm',
         'Waiting for admin  affairs  general manager to confirm'),
        ('approved', 'Waiting for admin  affairs manager to approve'),
        ('execute', 'Waiting for maintenance engineer to execute '),
        ('check', 'Waiting for the completion of maintenance'),
        ('done', 'Done'),
        ('cancel', 'Cancel'),
    ]

    PAYMENT_SELECTION = [
        ('voucher', 'Voucher'),
        ('enrich', 'Enrich'),
    ]

    _order = "name desc"
    _columns = {
        'name':
        fields.char('Reference',
                    size=64,
                    required=True,
                    select=True,
                    readonly=True,
                    help="unique number of the car maintenance "),
        'date':
        fields.date(
            'Request Date',
            required=True,
            readonly=True,
        ),
        #'department_id':  fields.related('car_id', 'department_id', type='many2one', relation='hr.department',store=True, string='Department',readonly=True,states={'draft':[('readonly',False)],'confirmed_d':[('readonly',False)],'confirmed_gd':[('readonly',False)],}),
        'department_id':
        fields.many2one('hr.department',
                        'Department',
                        states={
                            'approved': [('readonly', True)],
                            'approved_of': [('readonly', True)],
                            'execute': [('readonly', True)],
                            'check': [('readonly', True)],
                            'done': [('readonly', True)],
                            'cancel': [('readonly', True)]
                        }),
        'partner_id':
        fields.many2one('res.partner', 'Partner'),
        'car_id':
        fields.many2one('fleet.vehicle',
                        'Car Name',
                        required=True,
                        readonly=True,
                        states={
                            'draft': [('readonly', False)],
                            'confirmed_d': [('readonly', False)],
                            'confirmed_gd': [('readonly', False)],
                        }),
        #    'category_id':  fields.many2one('maintenance.category', 'Car Type'),
        'car_number':
        fields.related('car_id',
                       'license_plate',
                       type='char',
                       relation='fleet.vehicle',
                       string='Car Number',
                       readonly=True),
        'driver':
        fields.related('car_id',
                       'employee_id',
                       type='many2one',
                       relation='hr.employee',
                       string='Driver',
                       required=False,
                       readonly=True),
        'maintenance_date':
        fields.date('Maintenance Date',
                    required=True,
                    states={
                        'done': [('readonly', True)],
                        'cancel': [('readonly', True)]
                    }),
        'base_mileage':
        fields.related('car_id',
                       'cmil',
                       type='float',
                       relation='fleet.vehicle',
                       string='Current Mileage',
                       readonly=True,
                       help="The last recorded mileage"),
        'next_mileage':
        fields.float('Next Mileage',
                     digits=(16, 3),
                     help="The next mileage",
                     readonly=True,
                     states={
                         'draft': [('readonly', False)],
                         'confirmed_d': [('readonly', False)],
                         'confirmed_gd': [('readonly', False)],
                     }),
        'maintenance_type':
        fields.selection(MAINTENANCE_TYPE_SELECTION,
                         'Maintenance Type',
                         required=True,
                         readonly=True,
                         states={
                             'draft': [('readonly', False)],
                             'confirmed_d': [('readonly', False)],
                             'confirmed_gd': [('readonly', False)],
                         }),
        'notes':
        fields.text('Notes',
                    size=256,
                    readonly=True,
                    states={
                        'draft': [('readonly', False)],
                        'confirmed_d': [('readonly', False)],
                        'confirmed_gd': [('readonly', False)],
                    }),
        'company_id':
        fields.many2one('res.company', 'Company', required=True,
                        readonly=True),
        'faults':
        fields.one2many('car.faults',
                        'fault_id',
                        'Car Faults',
                        readonly=True,
                        states={
                            'draft': [('readonly', False)],
                            'execute': [('readonly', False)],
                            'confirmed_d': [('readonly', False)],
                            'check': [('readonly', False)],
                            'officer_of': [('readonly', False)],
                        }),
        'total_amount':
        fields.function(_amount_all,
                        method=True,
                        digits_compute=dp.get_precision('Account'),
                        string='Amount',
                        store=True),
        'state':
        fields.selection(STATE_SELECTION, 'State', readonly=True, select=True),
        'user_id':
        fields.many2one('res.users', 'Responsible', readonly=True),
        'voucher_no':
        fields.many2one('account.voucher', 'Voucher Number', readonly=True),
        'allowance_computed':
        fields.boolean('Allowance Computed', ),
        'next_maintenance_date':
        fields.date('Next Maintenance Date',
                    states={
                        'done': [('readonly', True)],
                        'cancel': [('readonly', True)]
                    }),
        'start_maintenance_date':
        fields.date('Start Maintenance Date',
                    states={
                        'done': [('readonly', True)],
                        'cancel': [('readonly', True)]
                    }),
        'end_maintenance_date':
        fields.date('End Maintenance Date',
                    states={
                        'done': [('readonly', True)],
                        'cancel': [('readonly', True)]
                    }),
        'payment_selection':
        fields.selection(PAYMENT_SELECTION,
                         'Payment',
                         readonly=True,
                         states={'check': [('readonly', False)]},
                         select=True),
        'enrich_category':
        fields.many2one('payment.enrich',
                        'Enrich',
                        readonly=True,
                        states={'check': [('readonly', False)]}),
    }

    _sql_constraints = [
        ('name_uniq', 'unique(name)',
         'car maintenance reference must be unique !'),
    ]

    _defaults = {
        'name':
        lambda self, cr, uid, context: '/',
        'date':
        lambda *a: time.strftime('%Y-%m-%d'),
        'company_id':
        lambda self, cr, uid, c: self.pool.get('res.company').
        _company_default_get(cr, uid, 'car.maintenance.request', context=c),
        'state':
        'draft',
        'user_id':
        lambda self, cr, uid, context: uid,
        'allowance_computed':
        lambda *a: 0,
    }
    """ Workflow Functions"""

    def confirmed_d(self, cr, uid, ids, context=None):
        """
           Workflow method that changes the state to 'confirmed_d'.
           @return: Boolean True
        """
        #for record in self.browse(cr, uid, ids):
        #if not record.faults:
        #raise orm.except_orm(_('No Faults  !'), _('Please Fault Item Details ..'))
        self.write(cr, uid, ids, {'state': 'confirmed_d'})
        return True

    def confirmed_gd(self, cr, uid, ids, context=None):
        """
           Workflow method that changes the state to 'confirmed_gd'.
           @return: Boolean True
        """
        self.write(cr, uid, ids, {'state': 'confirmed_gd'})
        return True

    def is_emergency(self, cr, uid, ids, context=None):
        """
           Workflow method that checks wether the maintenance request is for emergency or not.
           @return: Boolean True Or False
        """
        for record in self.browse(cr, uid, ids):
            if record.maintenance_type != "emergency":
                return False
        return True

    def is_roof(self, cr, uid, ids, context=None):
        """
           Workflow method that checks wether the amount of maintenance request has a financial roof  or not .
           @return: Boolean True Or False
        """
        affairs_model_obj = self.pool.get('admin.affairs.model')
        payment_roof_obj = self.pool.get('admin.affaris.payment.roof')
        for record in self.browse(cr, uid, ids):
            if record.maintenance_type == "emergency":
                affairs_model_ids = affairs_model_obj.search(
                    cr,
                    uid, [('model', '=', 'car.maintenance')],
                    context=context)
                if not affairs_model_ids:
                    return True
                payment_roof_ids = payment_roof_obj.search(
                    cr,
                    uid, [('model_id', '=', affairs_model_ids[0]),
                          ('name', '=', 'service')],
                    context=context)
                affairs_payment = payment_roof_obj.browse(cr,
                                                          uid,
                                                          payment_roof_ids[0],
                                                          context=context)
                if record.total_amount > affairs_payment.cost_to:
                    return False
        return True

    def is_regular(self, cr, uid, ids, context=None):
        """
           Workflow method that checks wether the maintenance type is regular or not .
           @return: Boolean True Or False
        """
        for record in self.browse(cr, uid, ids):
            if record.maintenance_type != "regular":
                return False
        return True

    def confirmed_gm(self, cr, uid, ids, context=None):
        """
           Workflow method that changes the state to 'confirmed_gm'.
           @return: Boolean True 
        """
        self.write(cr, uid, ids, {'state': 'confirmed_gm'}, context=context)
        return True

    def approved(self, cr, uid, ids, context=None):
        """
           Workflow method that changes the state to 'approved'.
           @return: Boolean True 
        """
        self.write(cr, uid, ids, {'state': 'approved'}, context=context)
        return True

    def approved_of(self, cr, uid, ids, context=None):
        """
           Workflow method that changes the state to 'approved_of'.
           @return: Boolean True 
        """
        self.write(cr, uid, ids, {'state': 'approved_of'}, context=context)
        return True

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

    def officer_of(self, cr, uid, ids, context=None):
        """
           Workflow method that changes the state to 'officer_of'.
           @return: Boolean True 
        """
        self.write(cr, uid, ids, {'state': 'officer_of'}, context=context)
        return True

    def execute(self, cr, uid, ids, context=None):
        """
           Workflow method that changes the state to 'execute'.
           @return: Boolean True 
        """
        self.write(cr, uid, ids, {'state': 'execute'}, context=context)
        return True

    def check(self, cr, uid, ids, context=None):
        """
           Workflow method that changes the state to 'check' and checks the Faults have been entered and that it has prices.
           @return: Boolean True 
        """
        payment_enrich_obj = self.pool.get('payment.enrich')
        payment_enrich_lines_obj = self.pool.get('payment.enrich.lines')
        for record in self.browse(cr, uid, ids):
            if not record.faults:
                raise osv.except_osv(_('No Faults  !'),
                                     _('Please Fault Item Details ..'))
            if record.payment_selection == 'enrich':
                paid = (record.enrich_category.paid_amount +
                        record.total_amount)
                residual = (record.enrich_category.residual_amount -
                            record.total_amount)
                #enrich_payment_id = cr.execute("""update payment_enrich set paid_amount=%s , residual_amount=%s where id =%s""",(paid,residual,record.enrich_category.id))
                #details = smart_str('Service Request No:'+record.name+'\n'+record.service_category.name)
                details = 'Car Maintenance No:' + record.name
                enrich_payment_lines_id = payment_enrich_lines_obj.create(
                    cr,
                    uid, {
                        'enrich_id': record.enrich_category.id,
                        'cost': record.total_amount,
                        'date': record.date,
                        'name': details,
                        'department_id': record.department_id.id,
                    },
                    context=context)
                self.write(cr,
                           uid,
                           ids, {'allowance_computed': True},
                           context=context)
            elif record.payment_selection == 'voucher':
                self.write(cr,
                           uid,
                           ids, {'allowance_computed': False},
                           context=context)
            for fault in record.faults:
                fault.write({'added_by_supplier': False})
                if fault.price_unit == 0.0:
                    raise osv.except_osv(
                        _('No Price !'),
                        _('Please make sure you enter prices for all items'))
        self.write(cr, uid, ids, {'state': 'check'}, context=context)
        return True

    def done(self, cr, uid, ids, context=None):
        """
           Workflow method that changes the state to 'done' and updates next_mileage of fleet vehicle.
           @return: Boolean True 
        """
        for record in self.browse(cr, uid, ids):

            self.pool.get('fleet.vehicle').write(cr, uid, [record.car_id.id],
                                                 {'cmil': record.next_mileage})
        self.write(cr, uid, ids, {'state': 'done'}, context=context)
        return True

    def modify_maintenance_request(self, cr, uid, ids, context=None):
        """
           Method that deletes the old Maintenance request's workflow and creat a new one in the 'check' state.
           @return: Boolean True 
        """
        if not len(ids):
            return False
        wf_service = netsvc.LocalService("workflow")
        for s_id in ids:
            wf_service.trg_delete(uid, 'car.maintenance.request', s_id, cr)
            wf_service.trg_create(uid, 'car.maintenance.request', s_id, cr)
            res = wf_service.trg_validate(uid, 'car.maintenance.request', s_id,
                                          'draft', cr)
            res = wf_service.trg_validate(uid, 'car.maintenance.request', s_id,
                                          'confirmed_d', cr)
            res = wf_service.trg_validate(uid, 'car.maintenance.request', s_id,
                                          'confirmed_gd', cr)
            res = wf_service.trg_validate(uid, 'car.maintenance.request', s_id,
                                          'approved_of', cr)
            res = wf_service.trg_validate(uid, 'car.maintenance.request', s_id,
                                          'officer_of', cr)
            res = wf_service.trg_validate(uid, 'car.maintenance.request', s_id,
                                          'confirmed_gm', cr)
            res = wf_service.trg_validate(uid, 'car.maintenance.request', s_id,
                                          'approved', cr)
            res = wf_service.trg_validate(uid, 'car.maintenance.request', s_id,
                                          'execute', cr)
            res = wf_service.trg_validate(uid, 'car.maintenance.request', s_id,
                                          'check', cr)
            #self.write(cr, uid, s_id, {'state':'dept_confirm'})
        return True

    def cancel(self, cr, uid, ids, notes='', context=None):
        """
           Method changes state of To 'cancel' and write notes about the cancellation.
	   @param notes: contains information of who & when cancelling the car maintenance request.
           @return: Boolean True
        """
        notes = ""
        u = self.pool.get('res.users').browse(cr, uid, uid).name
        notes = notes + '\n' + 'Car Maintenance Request Cancelled at : ' + time.strftime(
            '%Y-%m-%d') + ' by ' + u
        self.write(cr, uid, ids, {'state': 'cancel', 'notes': notes})
        return True

    def ir_action_cancel_draft(self, cr, uid, ids, context=None):
        """
           Method resets the Car Maintenance Request  record to 'draft' , deletes the old workflow and creates a new one.
           @return: Boolean True       
        """
        if not len(ids):
            return False
        wf_service = netsvc.LocalService("workflow")
        for s_id in ids:
            self.write(cr, uid, s_id, {'state': 'draft'})
            wf_service.trg_delete(uid, 'car.maintenance.request', s_id, cr)
            wf_service.trg_create(uid, 'car.maintenance.request', s_id, cr)
        return True

    def unlink(self, cr, uid, ids, context=None):
        """
           Method that overwrites unlink method to prevent the the deletion of  Car Maintenance Request record not in 'draft' state.
           @return: Super unlink method       
        """
        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 car maintenance request, \
							you must first cancel it,and set to draft.'))
        return super(car_maintenance_request, self).unlink(self,
                                                           cr,
                                                           uid,
                                                           unlink_ids,
                                                           context=context)

    def create_financial_voucher(self, cr, uid, ids, context=None):
        """
           Method that transfers the cost of maintenance to the voucher and creates a ratification for car's maintenance request .
           @return: Dictionary of values
        """
        names = ''
        voucher_obj = self.pool.get('account.voucher')
        voucher_line_obj = self.pool.get('account.voucher.line')
        for request in self.browse(cr, uid, ids, context=context):
            for pro in request.faults:
                names += pro.name + '\n'
            notes = _(
                "Car Maintenance : %s \nMaintenance Type: %s.\nSpare Part: %s."
            ) % (request.name, request.maintenance_type, names)
            config_id = self.pool.get('admin_affairs.account').search(
                cr,
                uid, [('company_id', '=', request.company_id.id)],
                context=context)
            if not config_id:
                raise osv.except_osv(
                    _('Invalid action !'),
                    _('Please insert the Company Configruation Account For Car Maintenance'
                      ))
            account_config = self.pool.get('admin_affairs.account').browse(
                cr, uid, config_id[0])
            # Creating Voucher / Ratitication
            voucher_id = voucher_obj.create(
                cr,
                uid, {
                    'amount': request.total_amount,
                    'type': 'ratification',
                    'date': time.strftime('%Y-%m-%d'),
                    'partner_id': request.partner_id.id,
                    'department_id': request.department_id.id,
                    'journal_id': account_config.maintenance_jorunal_id.id,
                    'state': 'draft',
                    'notes': request.notes,
                    'narration': notes,
                },
                context=context)
            voucher_line_dict = {
                'voucher_id':
                voucher_id,
                'account_id':
                account_config.maintenance_account_id.id,
                'account_analytic_id':
                account_config.maintenance_analytic_id.id
                or request.department_id.analytic_account_id.id,
                'amount':
                request.total_amount,
                'type':
                'dr',
                'name':
                request.department_id.name,
            }
            voucher_line_obj.create(cr,
                                    uid,
                                    voucher_line_dict,
                                    context=context)
            #################### update workflow state###############
            voucher_state = 'draft'
            if record.company_id.affairs_voucher_state:
                voucher_state = record.company_id.affairs_voucher_state
            if voucher_id:
                wf_service = netsvc.LocalService("workflow")
                wf_service.trg_validate(uid, 'account.voucher', voucher_id,
                                        voucher_state, cr)
                voucher_obj.write(
                    cr, uid, voucher_id, {
                        'type': 'ratification',
                        'ratification': True,
                        'state': voucher_state
                    }, context)
            # Selecting Voucher Number / Refernece
            #voucher_number = voucher_obj.browse(cr,uid,voucher_id,context=context).number
            self.write(cr,
                       uid,
                       request.id, {'voucher_no': voucher_id},
                       context=context)
        return True
Example #20
0
            ('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')
            ], 'Address Validation', help=''' No Validation = No address validation.
                                              Validate = Fail on failed address validation.
                                              Defaults to validate. Note: Full address validation is not performed. Therefore, it is
                                              the responsibility of the Shipping Tool User to ensure the address entered is correct to
                                              avoid an address correction fee.'''),
        'ship_description': fields.text('Description'),
        'ship_from': fields.boolean('Ship From', help='Required if pickup location is different from the shipper\'s address..'),
        'ship_from_tax_id_no': fields.char('Identification Number', size=30 , select=1),
        'shipcharge': fields.float('Shipping Cost', readonly=True),
        'ship_from_address': fields.many2one('res.partner', 'Ship From Address', size=30),
#         'address': fields.many2one('res.partner', 'Ship From Address'),
        'tot_order_weight': fields.related('sale_id', 'total_weight_net', type='float', relation='sale.order', string='Total Order Weight'),
        'comm_inv': fields.boolean('Commercial Invoice'),
        'cer_orig': fields.boolean('U.S. Certificate of Origin'),
        'nafta_cer_orig': fields.boolean('NAFTA Certificate of Origin'),
        'sed': fields.boolean('Shipper Export Declaration (SED)'),
        'prod_option': fields.selection([
            ('01', 'AVAILABLE TO CUSTOMS UPON REQUEST'),
            ('02', 'SAME AS EXPORTER'),
            ('03', 'ATTACHED LIST'),
            ('04', 'UNKNOWN'),
            (' ', ' ')
            ], 'Option'),
        'prod_company': fields.char('CompanyName', size=256, help='Only applicable when producer option is empty or not present.'),
Example #21
0
class car_faults(osv.Model):
    _name = "car.faults"
    _description = 'Type of Fault'

    def _amount_line(self, cr, uid, ids, field_name, arg, context=None):
        """ 
           Functional field function that calculates the cost of each car fault line ( quantity*price ).
           @param field_name: List contains name of fields that call this method
           @param arg: Extra arguement
           @return: Dictionary of values
        """
        context.update({'ids': ids})
        res = {}
        if context is None:
            context = {}
        for line in self.browse(cr, uid, ids, context=context):
            price = line.price_unit * line.product_qty or 0.0
            res[line.id] = price
        return res

    _columns = {
        'name':
        fields.char(
            'Name',
            size=64,
            select=True,
        ),
        'product_id':
        fields.many2one('product.product',
                        'Item',
                        required=True,
                        readonly=True,
                        states={
                            'draft': [('readonly', False)],
                            'execute': [('readonly', False)],
                            'check': [('readonly', False)],
                        }),
        'product_qty':
        fields.float('Item Quantity',
                     required=True,
                     digits=(16, 2),
                     readonly=True,
                     states={
                         'draft': [('readonly', False)],
                         'execute': [('readonly', False)],
                         'check': [('readonly', False)],
                     }),
        'product_uom':
        fields.many2one('product.uom',
                        'Item UOM',
                        readonly=True,
                        states={
                            'draft': [('readonly', False)],
                            'execute': [('readonly', False)],
                            'check': [('readonly', False)],
                        }),
        'fault_id':
        fields.many2one('car.maintenance.request',
                        'car maintenance request',
                        ondelete='cascade'),
        'price_unit':
        fields.float('Unit Price',
                     digits_compute=dp.get_precision('Account'),
                     readonly=True,
                     store=True,
                     states={
                         'draft': [('readonly', False)],
                         'confirmed_d': [('readonly', False)],
                         'execute': [('readonly', False)],
                         'check': [('readonly', False)],
                         'officer_of': [('readonly', False)],
                     }),
        'price_subtotal':
        fields.function(_amount_line,
                        method=True,
                        string='Sub total',
                        digits_compute=dp.get_precision('Account'),
                        readonly=True,
                        store=True),
        'added_by_supplier':
        fields.boolean(
            'Added by supplier',
            help=
            "By checking the Added by supplier field, you determine this product as adding by supplier",
            readonly=True,
        ),
        'state':
        fields.related(
            'fault_id',
            'state',
            type='char',
            relation='car.maintenance.request',
            string=' State',
            readonly=True,
        ),
        'notes':
        fields.text(
            'Notes',
            size=256,
        ),
    }
    _sql_constraints = [
        ('produc_uniq', 'unique(fuel_id,product_id)', 'Fault must be unique!'),
    ]

    _defaults = {
        'product_qty': 1.0,
        'added_by_supplier': True,
        'state': 'draft',
    }

    def product_id_change(self, cr, uid, ids, product, context=None):
        """
           Method that reads the default name and UOM of the given product id.
           @param product: Id of product 
           @return: Dictionary of values
        """
        if product:
            prod = self.pool.get('product.product').browse(cr, uid, product)
            return {
                'value': {
                    'name': prod.name,
                    'product_uom': prod.uom_po_id.id
                }
            }

#----------------------------------------
# Class car maintenance roof
#----------------------------------------
#class car_maintenance_roof(osv.Model):

    """def _check_roof_cost(self, cr, uid, ids, context=None): 
         ]

    def _get_size_usps(self, cr, uid, context=None):
        return [
            ('REGULAR', 'Regular'),
            ('LARGE', 'Large'),
         ]
    _columns= {
                    'ship_company_code': fields.selection(_get_company_code, 'Ship Company', method=True, size=64),
                    'usps_service_type' : fields.selection(_get_service_type_usps, 'Service Type', size=100),
                    'usps_package_location' : fields.selection([
                            ('Front Door','Front Door'),
                            ('Back Door','Back Door'),
                            ('Side Door','Side Door'),
                            ('Knock on Door/Ring Bell','Knock on Door/Ring Bell'),
                            ('Mail Room','Mail Room'),
                            ('Office','Office'),
                            ('Reception','Reception'),
                            ('In/At Mailbox','In/At Mailbox'),
                            ('Other','Other'),
                       ],'Package Location'),
                    'usps_first_class_mail_type' : fields.selection(_get_first_class_mail_type_usps, 'First Class Mail Type', size=50),
                    'usps_container' : fields.selection(_get_container_usps,'Container', size=100),
                    'usps_size' : fields.selection(_get_size_usps,'Size'),
                    'usps_length' : fields.float('Length'),
                    'usps_width' :  fields.float('Width'),
                    'usps_height' :  fields.float('Height'),
                    'usps_girth' :  fields.float('Girth'),
            }
shipping_rate_wizard()
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
Example #23
0
class report_invoice_created(osv.osv):
    _name = "report.invoice.created"
    _description = "Report of Invoices Created within Last 15 days"
    _auto = False
    _columns = {
        'name':
        fields.char('Description', readonly=True),
        'type':
        fields.selection([
            ('out_invoice', 'Customer Invoice'),
            ('in_invoice', 'Supplier Invoice'),
            ('out_refund', 'Customer Refund'),
            ('in_refund', 'Supplier Refund'),
        ],
                         'Type',
                         readonly=True),
        'number':
        fields.char('Invoice Number', readonly=True),
        'partner_id':
        fields.many2one('res.partner', 'Partner', readonly=True),
        'amount_untaxed':
        fields.float('Untaxed', readonly=True),
        'amount_total':
        fields.float('Total', readonly=True),
        'currency_id':
        fields.many2one('res.currency', 'Currency', readonly=True),
        'date_invoice':
        fields.date('Invoice Date', readonly=True),
        'date_due':
        fields.date('Due Date', readonly=True),
        'residual':
        fields.float('Residual', readonly=True),
        'state':
        fields.selection([('draft', 'Draft'), ('proforma', 'Pro-forma'),
                          ('proforma2', 'Pro-forma'), ('open', 'Open'),
                          ('paid', 'Done'), ('cancel', 'Cancelled')],
                         'Status',
                         readonly=True),
        'origin':
        fields.char(
            'Source Document',
            readonly=True,
            help="Reference of the document that generated this invoice report."
        ),
        'create_date':
        fields.datetime('Create Date', readonly=True)
    }
    _order = 'create_date'

    def init(self, cr):
        tools.drop_view_if_exists(cr, 'report_invoice_created')
        cr.execute("""create or replace view report_invoice_created as (
            select
               inv.id as id, inv.name as name, inv.type as type,
               inv.number as number, inv.partner_id as partner_id,
               inv.amount_untaxed as amount_untaxed,
               inv.amount_total as amount_total, inv.currency_id as currency_id,
               inv.date_invoice as date_invoice, inv.date_due as date_due,
               inv.residual as residual, inv.state as state,
               inv.origin as origin, inv.create_date as create_date
            from
                account_invoice inv
            where
                (to_date(to_char(inv.create_date, 'YYYY-MM-dd'),'YYYY-MM-dd') <= CURRENT_DATE)
                AND
                (to_date(to_char(inv.create_date, 'YYYY-MM-dd'),'YYYY-MM-dd') > (CURRENT_DATE-15))
            )""")
Example #24
0
class PaymentTransaction(osv.Model):
    """ Transaction Model. Each specific acquirer can extend the model by adding
    its own fields.

    Methods that can be added in an acquirer-specific implementation:

     - ``<name>_create``: method receiving values used when creating a new
       transaction and that returns a dictionary that will update those values.
       This method can be used to tweak some transaction values.

    Methods defined for convention, depending on your controllers:

     - ``<name>_form_feedback(self, cr, uid, data, context=None)``: method that
       handles the data coming from the acquirer after the transaction. It will
       generally receives data posted by the acquirer after the transaction.
    """
    _name = 'payment.transaction'
    _description = 'Payment Transaction'
    _inherit = ['mail.thread']
    _order = 'id desc'
    _rec_name = 'reference'

    _columns = {
        'date_create': fields.datetime('Creation Date', readonly=True, required=True),
        'date_validate': fields.datetime('Validation Date'),
        'acquirer_id': fields.many2one(
            'payment.acquirer', 'Acquirer',
            required=True,
        ),
        'type': fields.selection(
            [('server2server', 'Server To Server'), ('form', 'Form')],
            string='Type', required=True),
        'state': fields.selection(
            [('draft', 'Draft'), ('pending', 'Pending'),
             ('done', 'Done'), ('error', 'Error'),
             ('cancel', 'Canceled')
             ], 'Status', required=True,
            track_visiblity='onchange', copy=False),
        'state_message': fields.text('Message',
                                     help='Field used to store error and/or validation messages for information'),
        # payment
        'amount': fields.float('Amount', required=True,
                               digits=(16, 2),
                               track_visibility='always',
                               help='Amount in cents'),
        'fees': fields.float('Fees',
                             digits=(16, 2),
                             track_visibility='always',
                             help='Fees amount; set by the system because depends on the acquirer'),
        'currency_id': fields.many2one('res.currency', 'Currency', required=True),
        'reference': fields.char('Order Reference', required=True),
        'acquirer_reference': fields.char('Acquirer Order Reference',
                                          help='Reference of the TX as stored in the acquirer database'),
        # duplicate partner / transaction data to store the values at transaction time
        'partner_id': fields.many2one('res.partner', 'Partner', track_visibility='onchange',),
        'partner_name': fields.char('Partner Name'),
        'partner_lang': fields.char('Lang'),
        'partner_email': fields.char('Email'),
        'partner_zip': fields.char('Zip'),
        'partner_address': fields.char('Address'),
        'partner_city': fields.char('City'),
        'partner_country_id': fields.many2one('res.country', 'Country', required=True),
        'partner_phone': fields.char('Phone'),
        'partner_reference': fields.char('Partner Reference',
                                         help='Reference of the customer in the acquirer database'),
    }

    _sql_constraints = [
        ('reference_uniq', 'UNIQUE(reference)', 'The payment transaction reference must be unique!'),
    ]

    _defaults = {
        'date_create': fields.datetime.now,
        'type': 'form',
        'state': 'draft',
        'partner_lang': 'en_US',
    }

    def create(self, cr, uid, values, context=None):
        Acquirer = self.pool['payment.acquirer']

        if values.get('partner_id'):  # @TDENOTE: not sure
            values.update(self.on_change_partner_id(cr, uid, None, values.get('partner_id'), context=context)['values'])

        # call custom create method if defined (i.e. ogone_create for ogone)
        if values.get('acquirer_id'):
            acquirer = self.pool['payment.acquirer'].browse(cr, uid, values.get('acquirer_id'), context=context)

            # compute fees
            custom_method_name = '%s_compute_fees' % acquirer.provider
            if hasattr(Acquirer, custom_method_name):
                fees = getattr(Acquirer, custom_method_name)(
                    cr, uid, acquirer.id, values.get('amount', 0.0), values.get('currency_id'), values.get('country_id'), context=None)
                values['fees'] = float_round(fees, 2)

            # custom create
            custom_method_name = '%s_create' % acquirer.provider
            if hasattr(self, custom_method_name):
                values.update(getattr(self, custom_method_name)(cr, uid, values, context=context))

        return super(PaymentTransaction, self).create(cr, uid, values, context=context)

    def on_change_partner_id(self, cr, uid, ids, partner_id, context=None):
        partner = None
        if partner_id:
            partner = self.pool['res.partner'].browse(cr, uid, partner_id, context=context)
        return {'values': {
            'partner_name': partner and partner.name or False,
            'partner_lang': partner and partner.lang or 'en_US',
            'partner_email': partner and partner.email or False,
            'partner_zip': partner and partner.zip or False,
            'partner_address': _partner_format_address(partner and partner.street or '', partner and partner.street2 or ''),
            'partner_city': partner and partner.city or False,
            'partner_country_id': partner and partner.country_id.id or False,
            'partner_phone': partner and partner.phone or False,
        }}

    # --------------------------------------------------
    # FORM RELATED METHODS
    # --------------------------------------------------

    def form_feedback(self, cr, uid, data, acquirer_name, context=None):
        invalid_parameters, tx = None, None

        tx_find_method_name = '_%s_form_get_tx_from_data' % acquirer_name
        if hasattr(self, tx_find_method_name):
            tx = getattr(self, tx_find_method_name)(cr, uid, data, context=context)

        invalid_param_method_name = '_%s_form_get_invalid_parameters' % acquirer_name
        if hasattr(self, invalid_param_method_name):
            invalid_parameters = getattr(self, invalid_param_method_name)(cr, uid, tx, data, context=context)

        if invalid_parameters:
            _error_message = '%s: incorrect tx data:\n' % (acquirer_name)
            for item in invalid_parameters:
                _error_message += '\t%s: received %s instead of %s\n' % (item[0], item[1], item[2])
            _logger.error(_error_message)
            return False

        feedback_method_name = '_%s_form_validate' % acquirer_name
        if hasattr(self, feedback_method_name):
            return getattr(self, feedback_method_name)(cr, uid, tx, data, context=context)

        return True

    # --------------------------------------------------
    # SERVER2SERVER RELATED METHODS
    # --------------------------------------------------

    def s2s_create(self, cr, uid, values, cc_values, context=None):
        tx_id, tx_result = self.s2s_send(cr, uid, values, cc_values, context=context)
        self.s2s_feedback(cr, uid, tx_id, tx_result, context=context)
        return tx_id

    def s2s_send(self, cr, uid, values, cc_values, context=None):
        """ Create and send server-to-server transaction.

        :param dict values: transaction values
        :param dict cc_values: credit card values that are not stored into the
                               payment.transaction object. Acquirers should
                               handle receiving void or incorrect cc values.
                               Should contain :

                                - holder_name
                                - number
                                - cvc
                                - expiry_date
                                - brand
                                - expiry_date_yy
                                - expiry_date_mm
        """
        tx_id, result = None, None

        if values.get('acquirer_id'):
            acquirer = self.pool['payment.acquirer'].browse(cr, uid, values.get('acquirer_id'), context=context)
            custom_method_name = '_%s_s2s_send' % acquirer.provider
            if hasattr(self, custom_method_name):
                tx_id, result = getattr(self, custom_method_name)(cr, uid, values, cc_values, context=context)

        if tx_id is None and result is None:
            tx_id = super(PaymentTransaction, self).create(cr, uid, values, context=context)
        return (tx_id, result)

    def s2s_feedback(self, cr, uid, tx_id, data, context=None):
        """ Handle the feedback of a server-to-server transaction. """
        tx = self.browse(cr, uid, tx_id, context=context)
        invalid_parameters = None

        invalid_param_method_name = '_%s_s2s_get_invalid_parameters' % tx.acquirer_id.provider
        if hasattr(self, invalid_param_method_name):
            invalid_parameters = getattr(self, invalid_param_method_name)(cr, uid, tx, data, context=context)

        if invalid_parameters:
            _error_message = '%s: incorrect tx data:\n' % (tx.acquirer_id.name)
            for item in invalid_parameters:
                _error_message += '\t%s: received %s instead of %s\n' % (item[0], item[1], item[2])
            _logger.error(_error_message)
            return False

        feedback_method_name = '_%s_s2s_validate' % tx.acquirer_id.provider
        if hasattr(self, feedback_method_name):
            return getattr(self, feedback_method_name)(cr, uid, tx, data, context=context)

        return True

    def s2s_get_tx_status(self, cr, uid, tx_id, context=None):
        """ Get the tx status. """
        tx = self.browse(cr, uid, tx_id, context=context)

        invalid_param_method_name = '_%s_s2s_get_tx_status' % tx.acquirer_id.provider
        if hasattr(self, invalid_param_method_name):
            return getattr(self, invalid_param_method_name)(cr, uid, tx, context=context)

        return True
Example #25
0
class delivery_route_out_wizard_line(osv.osv_memory):
    """
        Movimientos de stock
    """
    _name = "delivery.route.out.wizard.line"

    def action_done(self, cr, uid, ids, context=None):
        """
            Prepara la carga al vehiculo de transportista
        """
        print "*****PREPARANDO LA CARGA AL VEHICULO DE TRANSPORTISTA*****"
        route_id = False
        res_id = False

        move_obj = self.pool.get('delivery.route.out.move')
        # Recorre las lineas a confirmar para obtener el movimiento
        for line in self.browse(cr, uid, ids, context=context):
            if line.move_id:
                # Valida que haya cantidad disponible para hacer la entrega
                if line.product_qty > line.virtual_available:
                    raise osv.except_osv(
                        _('Error'),
                        _("No hay producto disponible para surtir este pedido sobre la ruta la Ruta. (Producto: %s)"
                          % (line.name, )))
                print "****PONIENDO EL PRODUCTO COMO CARGADO EN LA CAMIONETA***"
                # Pone el producto como cargado en la camioneta
                move_obj.action_done(cr,
                                     uid, [line.move_id.id],
                                     context=context)
            route_id = line.route_id.id or False
            res_id = line.wizard_id.id or False

        # Revisa si hay movimientos pendientes
        move_ids = move_obj.search(cr, uid,
                                   [('route_id', '=', route_id),
                                    ('state', 'not in', ['cancel', 'done'])])
        print "****MOVE_IDS****: ", move_ids
        if move_ids:
            # Va a la parte de Preparar embarque
            return {
                'name': 'Preparar Embarque',
                'view_type': 'form',
                'view_mode': 'form',
                'res_model': 'delivery.route.out.wizard',
                'target': 'new',
                'context': {
                    'default_route_id': route_id
                },
                'type': 'ir.actions.act_window',
                'res_id': res_id
            }
        return self.pool.get('delivery.route').update_stock(cr,
                                                            uid, [route_id],
                                                            context=context)

    def _product_available(self, cr, uid, ids, name, arg, context=None):
        """
            Retorna el producto disponible sobre la tienda
        """
        product_obj = self.pool.get('product.product')
        res = {}
        if context is None:
            context = {}
        ctx = context.copy()
        ctx.update({
            'states': ('waiting', 'assigned', 'done'),
            'what': ('in', 'out')
        })
        #Recorre las lineas del producto
        for line in self.browse(cr, uid, ids, context=context):
            if not line.product_id:
                # Retorna 0 si no hay producto
                res[line.id] = 0.0
            else:
                # Obtiene el id de la ubicacion origen
                if line.location_id:
                    ctx['location'] = line.location_id.id
                # Asigna la stock virtual del producto a la linea del pedido de venta.
                stock = product_obj.get_product_available(cr,
                                                          uid,
                                                          [line.product_id.id],
                                                          context=ctx)
                print "********STOCK******: ", stock
                res[line.id] = stock.get(line.product_id.id, 0.0)
                # Aparta la cantidad de la existencia a cargar al transportista
                if line.state != 'done':
                    res[line.id] += line.product_qty
        return res

    _columns = {
        'name':
        fields.char('Descripcion', size=128),
        'wizard_id':
        fields.many2one('delivery.route.out.wizard',
                        'Wizard',
                        ondelete="cascade"),
        'move_id':
        fields.many2one('delivery.route.out.move',
                        'Movimiento Stock',
                        ondelete="cascade",
                        required=True),
        'route_id':
        fields.many2one('delivery.route', 'Ruta'),
        'product_id':
        fields.many2one('product.product', 'Producto'),
        'product_qty':
        fields.float('Cantidad'),
        'product_uom':
        fields.many2one('product.uom', 'Unidad de medida', ondelete="cascade"),
        'location_id':
        fields.many2one('stock.location',
                        'Ubicacion origen',
                        ondelete="set null"),
        'state':
        fields.related('move_id',
                       'state',
                       type="selection",
                       selection=[('draft', 'Por cargar'),
                                  ('cancel', 'Cancelado'),
                                  ('done', 'Realizado')],
                       string='Estado',
                       select=True),
        'virtual_available':
        fields.function(_product_available, type='float', string='Disponible'),
    }
Example #26
0
		cur_obj = self.pool.get('res.currency')
		#import pdb;pdb.set_trace()
		for line in self.browse(cr, uid, ids):
			#price = line.price_unit * (1-(line.discount or 0.0)/100.0)
			price = round(line.price_unit *line.quantity,3)
			# taxes = tax_obj.compute_all(cr, uid, line.invoice_line_tax_id, price, line.quantity, product=line.product_id, partner=line.invoice_id.partner_id)
			taxes = tax_obj.compute_all(cr, uid, line.invoice_line_tax_id, price, line.quantity, product=line.product_id, partner=line.invoice_id.partner_id)
			#res[line.id] = taxes['total']
			res[line.id] = price
			# if line.invoice_id:
			# 	cur = line.invoice_id.currency_id
			# 	res[line.id] = cur_obj.round(cr, uid, cur, res[line.id])
		return res

	_columns = {
		'quantity2': fields.float('Small Qty', digits_compute= dp.get_precision('Product Unit of Measure')),
		'uom_id' : fields.many2one('product.uom', 'Small UoM', ondelete='set null', select=True,required=True),
		'disc_tot': fields.float('Disc Total'),
		'price_subtotal': fields.function(_amount_line, string='Amount', type="float",
			digits_compute= dp.get_precision('Account'), store=True),
		'qty_func': fields.function(_get_tot_qty,string='Qty Tot'),
		'qty': fields.float('Qty', digits_compute= dp.get_precision('Product Unit of Measure')),
		'quantity': fields.function(_get_tot_qty,string='Quantity',type="float", digits_compute= dp.get_precision('Product Unit of Measure'), required=True),
		'price_unit2': fields.float('Price Unit 2'),
		'quantity3' : fields.float('Quantity PO'),

	}

	_defaults = {
		'uom_id' : _get_uom_id,
		} 
class wizard_payment_wht_specification_line(orm.TransientModel):
    _name = 'wizard.payment.wht.specification.line'
    _description = 'Wizard Payment Wht Specification Line'
    

    _columns = {
        'state': fields.selection([
            ('confirmed', 'Confirmed'),
            ('selected', 'Selected')], 'State'),
        'move_line_id': fields.many2one('account.move.line', 'Move Line'),
        'account_id': fields.many2one('account.account', 'Account'),
        'partner_id': fields.many2one('res.partner', 'Supplier'),
        'payment_specification_id': fields.many2one('wizard.payment.wht.specification',
                                         'Payment Specification',
                                         ondelete="cascade",
                                         required=True),
        'amount': fields.float('Amount')
         }
    
    
    
    def get_wizard_confirmed_filters(self, context=None):
        filters = []
        t_maturity = context.get('default_maturity', None)
        if(t_maturity):           
            f = ('date_maturity', '<=', t_maturity)
            filters.append(f)
        filters.append(('wht_state', '=', 'confirmed'))
        if(len(filters) > 1):
            filters.insert(0, '&')
        return filters
    
    def get_wizard_selected_filters(self, context=None):
        filters = []
        t_maturity = context.get('default_maturity', None)
        if(t_maturity):           
            f = ('date_maturity', '<=', t_maturity)
            filters.append(f)
        filters.append(('wht_state', '=', 'selected'))
        if(len(filters) > 1):
            filters.insert(0, '&')
        return filters

    
    def set_payment_lines(self, cr, uid, context=None):

        t_lines = []
        t_limit = 50
        t_page = context.get('default_actual_page', None)
        wizard_obj = self.pool.get('wizard.payment.wht.specification')
        wizard_wht_obj = self.pool.get('wizard.payment.wht')
        account_move_line_obj = self.pool.get('account.move.line')
       
        t_filters = self.get_wizard_confirmed_filters(context)
        
        t_total_pages = wizard_wht_obj.get_total_pages(cr, uid, t_filters, t_limit)
        
        if(t_page > t_total_pages or t_total_pages == 1):
            t_page = t_total_pages
            context.update({
                            'default_actual_page': t_page,
                           })
        
        t_offset = t_limit * (t_page - 1)
        
        res_id = wizard_obj.create(cr, uid, {
                                             'total_pages': t_total_pages,
                                             }, context)
        
        account_move_line_ids = account_move_line_obj.search(cr, uid, t_filters,
                                                             order='id',
                                                             limit=t_limit,
                                                             offset=t_offset,
                                                             context=context)
                
        for line in account_move_line_obj.browse(cr, uid, account_move_line_ids):
                            t_move_line_id = line.id
                            t_state = line.wht_state
                            t_lines.append((0, 0, {
                                                   'state': t_state,
                                                   'move_line_id': t_move_line_id,
                                                   'partner_id': line.partner_id.id,
                                                   'account_id': line.account_id.id,
                                                   'payment_specification_id': res_id,
                                                   'amount': line.credit
                                                   }))
       
        self.pool.get('wizard.payment.wht.specification').write(cr, uid, [res_id], {'confirmed_ids': t_lines, })
            
        t_lines = []
        t_filters = []
        t_filters = self.get_wizard_selected_filters(context)

        account_move_line_ids = account_move_line_obj.search(cr, uid, t_filters,
                                                             order='id',
                                                             context=context)
        
        for line in account_move_line_obj.browse(cr, uid, account_move_line_ids):
                            t_move_line_id = line.id
                            t_state = line.wht_state
                            t_lines.append((0, 0, {
                                                   'state': t_state,
                                                   'move_line_id': t_move_line_id,
                                                   'partner_id': line.partner_id.id,
                                                   'account_id': line.account_id.id,
                                                   'payment_specification_id': res_id,
                                                   'amount': line.credit
                                                   }))
       
        self.pool.get('wizard.payment.wht.specification').write(cr, uid, [res_id], {'selected_ids': t_lines, })
       
            
        return res_id
   
    
    
    def move_draft_forward(self, cr, uid, ids, context=None):
        if context is None:
            context = {}
        return self.move_draft(1, cr, uid, ids, context)

    def move_draft_backward(self, cr, uid, ids, context=None):
        if context is None:
            context = {}
        return self.move_draft(0, cr, uid, ids, context)
    
    def move_draft(self, fb, cr, uid, ids, context=None):
        if context is None:
            context = {}

        line_id = context.get('line_id', None)
        data = self.browse(cr, uid, line_id, context=context)
        t_journal = data.payment_specification_id.journal_id.id
        t_maturity = data.payment_specification_id.maturity
        t_page = data.payment_specification_id.actual_page
        
        t_state = 'confirmed'
        if fb:
            t_state = 'selected'
            
        draft_obj = self.pool.get('account.move.line')
        t_move_id = data.move_line_id.id
        draft_obj.write(cr, uid, [t_move_id], {
            'wht_state': t_state,
        })
#        t_move = data.move_line_id.move_id
        
        context.update({
            'default_journal_id': t_journal,
            'default_maturity': t_maturity,
            'default_actual_page': t_page,
        })
        
        res_id = self.set_payment_lines(cr, uid, context)

        mod_obj = self.pool.get('ir.model.data')
        result = mod_obj.get_object_reference(cr, uid,
                                              'account_voucher_makeover',
                                              'wizard_payment_wht_specification_view')
        view_id = result and result[1] or False

        return {
              'name': _("Wizard Wht Payment Specification"),
              'view_type': 'form',
              'view_mode': 'form',
              'res_model': 'wizard.payment.wht.specification',
              'type': 'ir.actions.act_window',
              'res_id': res_id,
              'view_id': view_id,
              'context': context,
              'target': 'inlineview',
              }
Example #28
0
class product_product(orm.Model):
    _inherit = "product.product"

    _columns = {
        'date_percentage': fields.float('Date percentage'),
    }
Example #29
0
class sale_order(osv.osv):
    _inherit = "sale.order"

    def _product_margin(self, cr, uid, ids, field_name, arg, context=None):
        result = {}
        for sale in self.browse(cr, uid, ids, context=context):
            result[sale.id] = 0.0
            for line in sale.order_line:
                result[sale.id] += line.margin or 0.0
            if sale.amount_untaxed > 0:
                sale.write(
                    {'margin_perc': result[sale.id] / sale.amount_untaxed})
            else:
                sale.write({'margin_perc': 0.0})
        return result

#    def _product_margin_perc(self, cr, uid, ids, field_name, arg, context=None):
#        result = {}
#        margin_order = {}
#        for sale in self.browse(cr, uid, ids, context=context):
#            margin_order[sale.id] = 0.0
#            for line in sale.order_line:
#                margin_order[sale.id] += line.margin or 0.0
#            if sale.amount_untaxed > 0:
#                result[sale.id] = margin_order[sale.id] / sale.amount_untaxed
#            else:
#                result[sale.id] = 0.0
#            	#result = 0.0
#        return result

    def _get_order(self, cr, uid, ids, context=None):
        result = {}
        for line in self.pool.get('sale.order.line').browse(cr,
                                                            uid,
                                                            ids,
                                                            context=context):
            result[line.order_id.id] = True
        return result.keys()

    _columns = {
        'margin':
        fields.function(
            _product_margin,
            string='Margin',
            help=
            "It gives profitability by calculating the difference between the Unit Price and the cost price.",
            store={
                'sale.order.line': (_get_order, ['margin',
                                                 'purchase_price'], 20),
                'sale.order':
                (lambda self, cr, uid, ids, c={}: ids, ['order_line'], 20),
            }),
        'margin_perc':
        fields.float(
            string='Margin Perc.',
            help=
            "It gives profitability by calculating the difference between the Unit Price and the cost price."
        )
        #      store={
        #        'margin_perc': fields.function(_product_margin_perc, string='Margin Perc.', help="It gives profitability by calculating the difference between the Unit Price and the cost price.", store={
        #                'sale.order.line': (_get_order, ['margin', 'purchase_price'], 20),
        #                'sale.order': (lambda self, cr, uid, ids, c={}: ids, ['order_line'], 20),
        #                }),
    }


# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
Example #30
0
class account_config_settings(osv.osv_memory):
    _name = 'account.config.settings'
    _inherit = 'res.config.settings'

    _columns = {
        'company_id': fields.many2one('res.company', 'Company', required=True),
        'has_default_company': fields.boolean('Has default company', readonly=True),
        'expects_chart_of_accounts': fields.related('company_id', 'expects_chart_of_accounts', type='boolean',
            string='This company has its own chart of accounts',
            help="""Check this box if this company is a legal entity."""),
        'currency_id': fields.related('company_id', 'currency_id', type='many2one', relation='res.currency', required=True,
            string='Default company currency', help="Main currency of the company."),
        'paypal_account': fields.related('company_id', 'paypal_account', type='char', size=128,
            string='Paypal account', help="Paypal account (email) for receiving online payments (credit card, etc.) If you set a paypal account, the customer  will be able to pay your invoices or quotations with a button \"Pay with  Paypal\" in automated emails or through the Odoo portal."),
        'company_footer': fields.related('company_id', 'rml_footer', type='text', readonly=True,
            string='Bank accounts footer preview', help="Bank accounts as printed in the footer of each printed document"),

        'has_chart_of_accounts': fields.boolean('Company has a chart of accounts'),
        'chart_template_id': fields.many2one('account.chart.template', 'Template', domain="[('visible','=', True)]"),
        'code_digits': fields.integer('# of Digits', help="No. of digits to use for account code"),
        'tax_calculation_rounding_method': fields.related('company_id',
            'tax_calculation_rounding_method', type='selection', selection=[
            ('round_per_line', 'Round per line'),
            ('round_globally', 'Round globally'),
            ], string='Tax calculation rounding method',
            help="If you select 'Round per line' : for each tax, the tax amount will first be computed and rounded for each PO/SO/invoice line and then these rounded amounts will be summed, leading to the total amount for that tax. If you select 'Round globally': for each tax, the tax amount will be computed for each PO/SO/invoice line, then these amounts will be summed and eventually this total tax amount will be rounded. If you sell with tax included, you should choose 'Round per line' because you certainly want the sum of your tax-included line subtotals to be equal to the total amount with taxes."),
        'sale_tax': fields.many2one("account.tax.template", "Default sale tax"),
        'purchase_tax': fields.many2one("account.tax.template", "Default purchase tax"),
        'sale_tax_rate': fields.float('Sales tax (%)'),
        'purchase_tax_rate': fields.float('Purchase tax (%)'),
        'complete_tax_set': fields.boolean('Complete set of taxes', help='This boolean helps you to choose if you want to propose to the user to encode the sales and purchase rates or use the usual m2o fields. This last choice assumes that the set of tax defined for the chosen template is complete'),

        'has_fiscal_year': fields.boolean('Company has a fiscal year'),
        'date_start': fields.date('Start date', required=True),
        'date_stop': fields.date('End date', required=True),
        'period': fields.selection([('month', 'Monthly'), ('3months','3 Monthly')], 'Periods', required=True),

        'sale_journal_id': fields.many2one('account.journal', 'Sale journal'),
        'sale_sequence_prefix': fields.related('sale_journal_id', 'sequence_id', 'prefix', type='char', string='Invoice sequence'),
        'sale_sequence_next': fields.related('sale_journal_id', 'sequence_id', 'number_next', type='integer', string='Next invoice number'),
        'sale_refund_journal_id': fields.many2one('account.journal', 'Sale refund journal'),
        'sale_refund_sequence_prefix': fields.related('sale_refund_journal_id', 'sequence_id', 'prefix', type='char', string='Credit note sequence'),
        'sale_refund_sequence_next': fields.related('sale_refund_journal_id', 'sequence_id', 'number_next', type='integer', string='Next credit note number'),
        'purchase_journal_id': fields.many2one('account.journal', 'Purchase journal'),
        'purchase_sequence_prefix': fields.related('purchase_journal_id', 'sequence_id', 'prefix', type='char', string='Supplier invoice sequence'),
        'purchase_sequence_next': fields.related('purchase_journal_id', 'sequence_id', 'number_next', type='integer', string='Next supplier invoice number'),
        'purchase_refund_journal_id': fields.many2one('account.journal', 'Purchase refund journal'),
        'purchase_refund_sequence_prefix': fields.related('purchase_refund_journal_id', 'sequence_id', 'prefix', type='char', string='Supplier credit note sequence'),
        'purchase_refund_sequence_next': fields.related('purchase_refund_journal_id', 'sequence_id', 'number_next', type='integer', string='Next supplier credit note number'),

        'module_account_check_writing': fields.boolean('Pay your suppliers by check',
            help='This allows you to check writing and printing.\n'
                 '-This installs the module account_check_writing.'),
        'module_account_accountant': fields.boolean('Full accounting features: journals, legal statements, chart of accounts, etc.',
            help="""If you do not check this box, you will be able to do invoicing & payments, but not accounting (Journal Items, Chart of  Accounts, ...)"""),
        'module_account_asset': fields.boolean('Assets management',
            help='This allows you to manage the assets owned by a company or a person.\n'
                 'It keeps track of the depreciation occurred on those assets, and creates account move for those depreciation lines.\n'
                 '-This installs the module account_asset. If you do not check this box, you will be able to do invoicing & payments, '
                 'but not accounting (Journal Items, Chart of Accounts, ...)'),
        'module_account_budget': fields.boolean('Budget management',
            help='This allows accountants to manage analytic and crossovered budgets. '
                 'Once the master budgets and the budgets are defined, '
                 'the project managers can set the planned amount on each analytic account.\n'
                 '-This installs the module account_budget.'),
        'module_account_payment': fields.boolean('Manage payment orders',
            help='This allows you to create and manage your payment orders, with purposes to \n'
                 '* serve as base for an easy plug-in of various automated payment mechanisms, and \n'
                 '* provide a more efficient way to manage invoice payments.\n'
                 '-This installs the module account_payment.' ),
        'module_account_voucher': fields.boolean('Manage customer payments',
            help='This includes all the basic requirements of voucher entries for bank, cash, sales, purchase, expense, contra, etc.\n'
                 '-This installs the module account_voucher.'),
        'module_account_followup': fields.boolean('Manage customer payment follow-ups',
            help='This allows to automate letters for unpaid invoices, with multi-level recalls.\n'
                 '-This installs the module account_followup.'),
        'module_product_email_template': fields.boolean('Send products tools and information at the invoice confirmation',
            help='With this module, link your products to a template to send complete information and tools to your customer.\n'
                 'For instance when invoicing a training, the training agenda and materials will automatically be send to your customers.'),
        'module_account_bank_statement_import_ofx': fields.boolean('Import of Bank Statements in .OFX Format',
            help='Get your bank statements from you bank and import them in Odoo in .OFX format.\n'
                '-that installs the module account_bank_statement_import.'),
        'module_account_bank_statement_import_qif': fields.boolean('Import of Bank Statements in .QIF Format.',
            help='Get your bank statements from you bank and import them in Odoo in .QIF format.\n'
                '-that installs the module account_bank_statement_import_qif.'),
        'group_proforma_invoices': fields.boolean('Allow pro-forma invoices',
            implied_group='account.group_proforma_invoices',
            help="Allows you to put invoices in pro-forma state."),
        'default_sale_tax': fields.many2one('account.tax', 'Default sale tax',
            help="This sale tax will be assigned by default on new products."),
        'default_purchase_tax': fields.many2one('account.tax', 'Default purchase tax',
            help="This purchase tax will be assigned by default on new products."),
        'decimal_precision': fields.integer('Decimal precision on journal entries',
            help="""As an example, a decimal precision of 2 will allow journal entries  like: 9.99 EUR, whereas a decimal precision of 4 will allow journal  entries like: 0.0231 EUR."""),
        'group_multi_currency': fields.boolean('Allow multi currencies',
            implied_group='base.group_multi_currency',
            help="Allows you multi currency environment"),
        'group_analytic_accounting': fields.boolean('Analytic accounting',
            implied_group='analytic.group_analytic_accounting',
            help="Allows you to use the analytic accounting."),
        'group_check_supplier_invoice_total': fields.boolean('Check the total of supplier invoices', 
            implied_group="account.group_supplier_inv_check_total"),
    }

    def _default_company(self, cr, uid, context=None):
        user = self.pool.get('res.users').browse(cr, uid, uid, context=context)
        return user.company_id.id

    def _default_has_default_company(self, cr, uid, context=None):
        count = self.pool.get('res.company').search_count(cr, uid, [], context=context)
        return bool(count == 1)

    def _get_default_fiscalyear_data(self, cr, uid, company_id, context=None):
        """Compute default period, starting and ending date for fiscalyear
        - if in a fiscal year, use its period, starting and ending date
        - if past fiscal year, use its period, and new dates [ending date of the latest +1 day ; ending date of the latest +1 year]
        - if no fiscal year, use monthly, 1st jan, 31th dec of this year
        :return: (date_start, date_stop, period) at format DEFAULT_SERVER_DATETIME_FORMAT
        """
        fiscalyear_ids = self.pool.get('account.fiscalyear').search(cr, uid,
                [('date_start', '<=', time.strftime(DF)), ('date_stop', '>=', time.strftime(DF)),
                 ('company_id', '=', company_id)])
        if fiscalyear_ids:
            # is in a current fiscal year, use this one
            fiscalyear = self.pool.get('account.fiscalyear').browse(cr, uid, fiscalyear_ids[0], context=context)
            if len(fiscalyear.period_ids) == 5:  # 4 periods of 3 months + opening period
                period = '3months'
            else:
                period = 'month'
            return (fiscalyear.date_start, fiscalyear.date_stop, period)
        else:
            past_fiscalyear_ids = self.pool.get('account.fiscalyear').search(cr, uid,
                [('date_stop', '<=', time.strftime(DF)), ('company_id', '=', company_id)])
            if past_fiscalyear_ids:
                # use the latest fiscal, sorted by (start_date, id)
                latest_year = self.pool.get('account.fiscalyear').browse(cr, uid, past_fiscalyear_ids[-1], context=context)
                latest_stop = datetime.datetime.strptime(latest_year.date_stop, DF)
                if len(latest_year.period_ids) == 5:
                    period = '3months'
                else:
                    period = 'month'
                return ((latest_stop+datetime.timedelta(days=1)).strftime(DF), latest_stop.replace(year=latest_stop.year+1).strftime(DF), period)
            else:
                return (time.strftime('%Y-01-01'), time.strftime('%Y-12-31'), 'month')


    _defaults = {
        'company_id': _default_company,
        'has_default_company': _default_has_default_company,
    }

    def create(self, cr, uid, values, context=None):
        id = super(account_config_settings, self).create(cr, uid, values, context)
        # Hack: to avoid some nasty bug, related fields are not written upon record creation.
        # Hence we write on those fields here.
        vals = {}
        for fname, field in self._columns.iteritems():
            if isinstance(field, fields.related) and fname in values:
                vals[fname] = values[fname]
        self.write(cr, uid, [id], vals, context)
        return id

    def onchange_company_id(self, cr, uid, ids, company_id, context=None):
        # update related fields
        values = {}
        values['currency_id'] = False
        if company_id:
            company = self.pool.get('res.company').browse(cr, uid, company_id, context=context)
            has_chart_of_accounts = company_id not in self.pool.get('account.installer').get_unconfigured_cmp(cr, uid)
            fiscalyear_count = self.pool.get('account.fiscalyear').search_count(cr, uid,
                [('date_start', '<=', time.strftime('%Y-%m-%d')), ('date_stop', '>=', time.strftime('%Y-%m-%d')),
                 ('company_id', '=', company_id)])
            date_start, date_stop, period = self._get_default_fiscalyear_data(cr, uid, company_id, context=context)
            values = {
                'expects_chart_of_accounts': company.expects_chart_of_accounts,
                'currency_id': company.currency_id.id,
                'paypal_account': company.paypal_account,
                'company_footer': company.rml_footer,
                'has_chart_of_accounts': has_chart_of_accounts,
                'has_fiscal_year': bool(fiscalyear_count),
                'chart_template_id': False,
                'tax_calculation_rounding_method': company.tax_calculation_rounding_method,
                'date_start': date_start,
                'date_stop': date_stop,
                'period': period,
            }
            # update journals and sequences
            for journal_type in ('sale', 'sale_refund', 'purchase', 'purchase_refund'):
                for suffix in ('_journal_id', '_sequence_prefix', '_sequence_next'):
                    values[journal_type + suffix] = False
            journal_obj = self.pool.get('account.journal')
            journal_ids = journal_obj.search(cr, uid, [('company_id', '=', company_id)])
            for journal in journal_obj.browse(cr, uid, journal_ids):
                if journal.type in ('sale', 'sale_refund', 'purchase', 'purchase_refund'):
                    values.update({
                        journal.type + '_journal_id': journal.id,
                        journal.type + '_sequence_prefix': journal.sequence_id.prefix,
                        journal.type + '_sequence_next': journal.sequence_id.number_next,
                    })
            # update taxes
            ir_values = self.pool.get('ir.values')
            taxes_id = ir_values.get_default(cr, uid, 'product.product', 'taxes_id', company_id=company_id)
            supplier_taxes_id = ir_values.get_default(cr, uid, 'product.product', 'supplier_taxes_id', company_id=company_id)
            values.update({
                'default_sale_tax': isinstance(taxes_id, list) and taxes_id[0] or taxes_id,
                'default_purchase_tax': isinstance(supplier_taxes_id, list) and supplier_taxes_id[0] or supplier_taxes_id,
            })
        return {'value': values}

    def onchange_chart_template_id(self, cr, uid, ids, chart_template_id, context=None):
        tax_templ_obj = self.pool.get('account.tax.template')
        res = {'value': {
            'complete_tax_set': False, 'sale_tax': False, 'purchase_tax': False,
            'sale_tax_rate': 15, 'purchase_tax_rate': 15,
        }}
        if chart_template_id:
            # update complete_tax_set, sale_tax and purchase_tax
            chart_template = self.pool.get('account.chart.template').browse(cr, uid, chart_template_id, context=context)
            res['value'].update({'complete_tax_set': chart_template.complete_tax_set})
            if chart_template.complete_tax_set:
                # default tax is given by the lowest sequence. For same sequence we will take the latest created as it will be the case for tax created while isntalling the generic chart of account
                sale_tax_ids = tax_templ_obj.search(cr, uid,
                    [("chart_template_id", "=", chart_template_id), ('type_tax_use', 'in', ('sale','all'))],
                    order="sequence, id desc")
                purchase_tax_ids = tax_templ_obj.search(cr, uid,
                    [("chart_template_id", "=", chart_template_id), ('type_tax_use', 'in', ('purchase','all'))],
                    order="sequence, id desc")
                res['value']['sale_tax'] = sale_tax_ids and sale_tax_ids[0] or False
                res['value']['purchase_tax'] = purchase_tax_ids and purchase_tax_ids[0] or False
            if chart_template.code_digits:
                res['value']['code_digits'] = chart_template.code_digits
        return res

    def onchange_tax_rate(self, cr, uid, ids, rate, context=None):
        return {'value': {'purchase_tax_rate': rate or False}}

    def onchange_multi_currency(self, cr, uid, ids, group_multi_currency, context=None):
        res = {}
        if not group_multi_currency:
            res['value'] = {'income_currency_exchange_account_id': False, 'expense_currency_exchange_account_id': False}
        return res
    
    def onchange_start_date(self, cr, uid, id, start_date):
        if start_date:
            start_date = datetime.datetime.strptime(start_date, "%Y-%m-%d")
            end_date = (start_date + relativedelta(months=12)) - relativedelta(days=1)
            return {'value': {'date_stop': end_date.strftime('%Y-%m-%d')}}
        return {}

    def open_company_form(self, cr, uid, ids, context=None):
        config = self.browse(cr, uid, ids[0], context)
        return {
            'type': 'ir.actions.act_window',
            'name': 'Configure your Company',
            'res_model': 'res.company',
            'res_id': config.company_id.id,
            'view_mode': 'form',
        }

    def set_default_taxes(self, cr, uid, ids, context=None):
        """ set default sale and purchase taxes for products """
        if uid != SUPERUSER_ID and not self.pool['res.users'].has_group(cr, uid, 'base.group_erp_manager'):
            raise openerp.exceptions.AccessError(_("Only administrators can change the settings"))
        ir_values = self.pool.get('ir.values')
        config = self.browse(cr, uid, ids[0], context)
        ir_values.set_default(cr, SUPERUSER_ID, 'product.product', 'taxes_id',
            config.default_sale_tax and [config.default_sale_tax.id] or False, company_id=config.company_id.id)
        ir_values.set_default(cr, SUPERUSER_ID, 'product.product', 'supplier_taxes_id',
            config.default_purchase_tax and [config.default_purchase_tax.id] or False, company_id=config.company_id.id)

    def set_chart_of_accounts(self, cr, uid, ids, context=None):
        """ install a chart of accounts for the given company (if required) """
        config = self.browse(cr, uid, ids[0], context)
        if config.chart_template_id:
            assert config.expects_chart_of_accounts and not config.has_chart_of_accounts
            wizard = self.pool.get('wizard.multi.charts.accounts')
            wizard_id = wizard.create(cr, uid, {
                'company_id': config.company_id.id,
                'chart_template_id': config.chart_template_id.id,
                'code_digits': config.code_digits or 6,
                'sale_tax': config.sale_tax.id,
                'purchase_tax': config.purchase_tax.id,
                'sale_tax_rate': config.sale_tax_rate,
                'purchase_tax_rate': config.purchase_tax_rate,
                'complete_tax_set': config.complete_tax_set,
                'currency_id': config.currency_id.id,
            }, context)
            wizard.execute(cr, uid, [wizard_id], context)

    def set_fiscalyear(self, cr, uid, ids, context=None):
        """ create a fiscal year for the given company (if necessary) """
        config = self.browse(cr, uid, ids[0], context)
        if config.has_chart_of_accounts or config.chart_template_id:
            fiscalyear = self.pool.get('account.fiscalyear')
            fiscalyear_count = fiscalyear.search_count(cr, uid,
                [('date_start', '<=', config.date_start), ('date_stop', '>=', config.date_stop),
                 ('company_id', '=', config.company_id.id)],
                context=context)
            if not fiscalyear_count:
                name = code = config.date_start[:4]
                if int(name) != int(config.date_stop[:4]):
                    name = config.date_start[:4] +'-'+ config.date_stop[:4]
                    code = config.date_start[2:4] +'-'+ config.date_stop[2:4]
                vals = {
                    'name': name,
                    'code': code,
                    'date_start': config.date_start,
                    'date_stop': config.date_stop,
                    'company_id': config.company_id.id,
                }
                fiscalyear_id = fiscalyear.create(cr, uid, vals, context=context)
                if config.period == 'month':
                    fiscalyear.create_period(cr, uid, [fiscalyear_id])
                elif config.period == '3months':
                    fiscalyear.create_period3(cr, uid, [fiscalyear_id])

    def get_default_dp(self, cr, uid, fields, context=None):
        dp = self.pool.get('ir.model.data').get_object(cr, uid, 'product','decimal_account')
        return {'decimal_precision': dp.digits}

    def set_default_dp(self, cr, uid, ids, context=None):
        config = self.browse(cr, uid, ids[0], context)
        dp = self.pool.get('ir.model.data').get_object(cr, uid, 'product','decimal_account')
        dp.write({'digits': config.decimal_precision})

    def onchange_analytic_accounting(self, cr, uid, ids, analytic_accounting, context=None):
        if analytic_accounting:
            return {'value': {
                'module_account_accountant': True,
                }}
        return {}
Example #31
0
class sale_order_line(osv.osv):
    _inherit = "sale.order.line"

    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):
        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 pricelist:
            return res
        if context is None:
            context = {}
        frm_cur = self.pool.get('res.users').browse(
            cr, uid, uid).company_id.currency_id.id
        to_cur = self.pool.get('product.pricelist').browse(
            cr, uid, [pricelist])[0].currency_id.id
        if product:
            product = self.pool['product.product'].browse(cr,
                                                          uid,
                                                          product,
                                                          context=context)
            #template = self.pool['product.template'].browse(cr, uid, template.product_tmpl_id=product, context=context)
            if product.variant_cost_price > 0:
                purchase_price = product.variant_cost_price
            else:
                purchase_price = product.standard_price
            to_uom = res.get('product_uom', uom)
            if to_uom != product.uom_id.id:
                purchase_price = self.pool['product.uom']._compute_price(
                    cr, uid, product.uom_id.id, purchase_price, to_uom)
            ctx = context.copy()
            ctx['date'] = date_order
            price = self.pool.get('res.currency').compute(cr,
                                                          uid,
                                                          frm_cur,
                                                          to_cur,
                                                          purchase_price,
                                                          round=False,
                                                          context=ctx)
            price = purchase_price
            res['value'].update({'purchase_price': price})
        return res

    def _product_margin(self, cr, uid, ids, field_name, arg, context=None):
        res = {}
        for line in self.browse(cr, uid, ids, context=context):
            res[line.id] = ''
            if line.product_id:
                res[line.id] = round(
                    line.price_subtotal -
                    ((line.purchase_price) * line.product_uos_qty), 2)
        return res

    _columns = {
        'margin': fields.function(_product_margin, string='Margin',
                                  store=True),
        'purchase_price': fields.float('Cost Price', digits=(16, 2))
    }
Example #32
0
class stock_move(osv.osv):
    _inherit = "stock.move"

    _columns = {
        'move_returned_from': fields.many2one('stock.move', 'Move this move was returned from'),
        'price_unit': fields.float('Unit Price', help="Technical field used to record the product cost set by the user during a picking confirmation (when average price costing method is used)"),
    }

    def _check_company_location(self, cr, uid, ids, context=None):
        for record in self.browse(cr, uid, ids, context=context):
            if record.location_id.company_id and (record.company_id.id != record.location_id.company_id.id):
                raise osv.except_osv(_('Error'), _('The company of the source location (%s) and the company of the stock move (%s) should be the same') % (record.location_id.company_id.name, record.company_id.name))
            if record.location_dest_id.company_id and (record.company_id.id != record.location_dest_id.company_id.id):
                raise osv.except_osv(_('Error'), _('The company of the destination location (%s) and the company of the stock move (%s) should be the same') % (record.location_dest_id.company_id.name, record.company_id.name))
        return True

    _constraints = [
        (_check_company_location, 'You cannot use a location from another company. ', 
            ['company_id', 'location_id', 'location_dest_id'])]

    def _default_location_destination(self, cr, uid, context=None):
        """ Gets default address of partner for destination location
        @return: Address id or False
        """
        mod_obj = self.pool.get('ir.model.data')
        picking_type = context.get('picking_type')
        location_id = False
        if context is None:
            context = {}
        if context.get('move_line', []):
            if context['move_line'][0]:
                if isinstance(context['move_line'][0], (tuple, list)):
                    location_id = context['move_line'][0][2] and context['move_line'][0][2].get('location_dest_id',False)
                else:
                    move_list = self.pool.get('stock.move').read(cr, uid, context['move_line'][0], ['location_dest_id'])
                    location_id = move_list and move_list['location_dest_id'][0] or False
        elif context.get('address_out_id', False):
            property_out = self.pool.get('res.partner').browse(cr, uid, context['address_out_id'], context).property_stock_customer
            location_id = property_out and property_out.id or False
        else:
            location_xml_id = False
            if picking_type in ('in', 'internal'):
                location_xml_id = 'stock_location_stock'
            elif picking_type == 'out':
                location_xml_id = 'stock_location_customers'
            if location_xml_id:
                location_model, location_id = mod_obj.get_object_reference(cr, uid, 'stock', location_xml_id)
                if location_id:
                    location_company = self.pool.get("stock.location").browse(cr, uid, location_id, context=context).company_id
                    user_company = self.pool.get("res.users").browse(cr, uid, uid, context=context).company_id.id
                    if location_company and location_company.id != user_company:
                        location_id = False
        return location_id

    def _default_location_source(self, cr, uid, context=None):
        """ Gets default address of partner for source location
        @return: Address id or False
        """
        mod_obj = self.pool.get('ir.model.data')
        picking_type = context.get('picking_type')
        location_id = False

        if context is None:
            context = {}
        if context.get('move_line', []):
            try:
                location_id = context['move_line'][0][2]['location_id']
            except:
                pass
        elif context.get('address_in_id', False):
            part_obj_add = self.pool.get('res.partner').browse(cr, uid, context['address_in_id'], context=context)
            if part_obj_add:
                location_id = part_obj_add.property_stock_supplier.id
        else:
            location_xml_id = False
            if picking_type == 'in':
                location_xml_id = 'stock_location_suppliers'
            elif picking_type in ('out', 'internal'):
                location_xml_id = 'stock_location_stock'
            if location_xml_id:
                location_model, location_id = mod_obj.get_object_reference(cr, uid, 'stock', location_xml_id)
                if location_id:
                    location_company = self.pool.get("stock.location").browse(cr, uid, location_id, context=context).company_id
                    user_company = self.pool.get("res.users").browse(cr, uid, uid, context=context).company_id.id
                    if location_company and location_company.id != user_company:
                        location_id = False
        return location_id

    def onchange_move_type(self, cr, uid, ids, type, context=None):
        """ On change of move type gives sorce and destination location.
        @param type: Move Type
        @return: Dictionary of values
        """
        mod_obj = self.pool.get('ir.model.data')
        location_source_id = 'stock_location_stock'
        location_dest_id = 'stock_location_stock'
        if type == 'in':
            location_source_id = 'stock_location_suppliers'
            location_dest_id = 'stock_location_stock'
        elif type == 'out':
            location_source_id = 'stock_location_stock'
            location_dest_id = 'stock_location_customers'
        source_location = mod_obj.get_object_reference(cr, uid, 'stock', location_source_id)
        dest_location = mod_obj.get_object_reference(cr, uid, 'stock', location_dest_id)
        #Check companies
        user_company = self.pool.get("res.users").browse(cr, uid, uid, context=context).company_id.id
        if source_location:
            location_company = self.pool.get("stock.location").browse(cr, uid, source_location[1], context=context).company_id
            if location_company and location_company.id != user_company:
                source_location = False
        if dest_location:
            location_company = self.pool.get("stock.location").browse(cr, uid, dest_location[1], context=context).company_id
            if location_company and location_company.id != user_company:
                dest_location = False
        return {'value':{'location_id': source_location and source_location[1] or False, 'location_dest_id': dest_location and dest_location[1] or False}}

    #We can use a preliminary type
    def get_reference_amount(self, cr, uid, move, qty, context=None):
        # if product is set to average price and a specific value was entered in the picking wizard,
        # we use it

        # by default the reference currency is that of the move's company
        reference_currency_id = move.company_id.currency_id.id
        
        #I use 
        if move.product_id.cost_method != 'standard' and move.price_unit:
            reference_amount = move.product_qty * move.price_unit #Using move.price_qty instead of qty to have correct amount
            reference_currency_id = move.price_currency_id.id or reference_currency_id

        # Otherwise we default to the company's valuation price type, considering that the values of the
        # valuation field are expressed in the default currency of the move's company.
        else:
            if context is None:
                context = {}
            currency_ctx = dict(context, currency_id = move.company_id.currency_id.id)
            amount_unit = move.product_id.price_get('standard_price', context=currency_ctx)[move.product_id.id]
            reference_amount = amount_unit * qty
        
        return reference_amount, reference_currency_id

    def _get_reference_accounting_values_for_valuation(self, cr, uid, move, context=None):
        """
        Return the reference amount and reference currency representing the inventory valuation for this move.
        These reference values should possibly be converted before being posted in Journals to adapt to the primary
        and secondary currencies of the relevant accounts.
        """
        product_uom_obj = self.pool.get('product.uom')

        default_uom = move.product_id.uom_id.id
        qty = product_uom_obj._compute_qty(cr, uid, move.product_uom.id, move.product_qty, default_uom)
        
        reference_amount, reference_currency_id = self.get_reference_amount(cr, uid, move, qty, context=context)
        return reference_amount, reference_currency_id

    def _create_product_valuation_moves(self, cr, uid, move, matches, context=None):
        """
        Generate the appropriate accounting moves if the product being moved is subject
        to real_time valuation tracking, and the source or the destination location is internal (not both)
        This means an in or out move. 
        
        Depending on the matches it will create the necessary moves
        """
        ctx = context.copy()
        ctx['force_company'] = move.company_id.id
        valuation = self.pool.get("product.product").browse(cr, uid, move.product_id.id, context=ctx).valuation
        move_obj = self.pool.get('account.move')
        if valuation == 'real_time':
            if context is None:
                context = {}
            company_ctx = dict(context,force_company=move.company_id.id)
            journal_id, acc_src, acc_dest, acc_valuation = self._get_accounting_data_for_valuation(cr, uid, move, context=company_ctx)
            reference_amount, reference_currency_id = self._get_reference_accounting_values_for_valuation(cr, uid, move, context=company_ctx)
            account_moves = []
            # Outgoing moves (or cross-company output part)
            if move.location_id.company_id \
                and (move.location_id.usage == 'internal' and move.location_dest_id.usage != 'internal'):
                #returning goods to supplier
                if move.location_dest_id.usage == 'supplier':
                    account_moves += [(journal_id, self._create_account_move_line(cr, uid, move, matches, acc_valuation, acc_src, reference_amount, reference_currency_id, 'out', context=company_ctx))]
                else:
                    account_moves += [(journal_id, self._create_account_move_line(cr, uid, move, matches, acc_valuation, acc_dest, reference_amount, reference_currency_id, 'out', context=company_ctx))]

            # Incoming moves (or cross-company input part)
            if move.location_dest_id.company_id \
                and (move.location_id.usage != 'internal' and move.location_dest_id.usage == 'internal'):
                #goods return from customer
                if move.location_id.usage == 'customer':
                    account_moves += [(journal_id, self._create_account_move_line(cr, uid, move, matches, acc_dest, acc_valuation, reference_amount, reference_currency_id, 'in', context=company_ctx))]
                else:
                    account_moves += [(journal_id, self._create_account_move_line(cr, uid, move, matches, acc_src, acc_valuation, reference_amount, reference_currency_id, 'in', context=company_ctx))]
                if matches and move.product_id.cost_method in ('fifo', 'lifo'):
                    outs = {}
                    match_obj = self.pool.get("stock.move.matching")
                    for match in match_obj.browse(cr, uid, matches, context=context):
                        if match.move_out_id.id in outs:
                            outs[match.move_out_id.id] += [match.id]
                        else:
                            outs[match.move_out_id.id] = [match.id]
                    #When in stock was negative, you will get matches for the in also:
                    account_moves_neg = []
                    for out_mov in self.browse(cr, uid, outs.keys(), context=context):
                        journal_id_out, acc_src_out, acc_dest_out, acc_valuation_out = self._get_accounting_data_for_valuation(cr, uid, out_mov, context=company_ctx)
                        reference_amount_out, reference_currency_id_out = self._get_reference_accounting_values_for_valuation(cr, uid, out_mov, context=company_ctx)
                        if out_mov.location_dest_id.usage == 'supplier':
                            # Is not the way it should be with acc_valuation
                            account_moves_neg += [(journal_id_out, self._create_account_move_line(cr, uid, out_mov, outs[out_mov.id], acc_valuation_out, acc_src_out, reference_amount_out, reference_currency_id_out, 'out', context=company_ctx))]
                        else:
                            account_moves_neg += [(journal_id_out, self._create_account_move_line(cr, uid, out_mov, outs[out_mov.id], acc_valuation_out, acc_dest_out, reference_amount_out, reference_currency_id_out, 'out', context=company_ctx))]
                    #Create account moves for outs which made stock go negative
                    for j_id, move_lines in account_moves_neg:
                        move_obj.create(cr, uid,
                                        {'journal_id': j_id, 
                                         'line_id': move_lines, 
                                         'ref': out_mov.picking_id and out_mov.picking_id.name,
                                         })
            for j_id, move_lines in account_moves:
                move_obj.create(cr, uid,
                        {
                         'journal_id': j_id,
                         'line_id': move_lines,
                         'ref': move.picking_id and move.picking_id.name})

    def action_done(self, cr, uid, ids, context=None):
        """ Makes the move done and if all moves are done, it will finish the picking.
        @return:
        """
        picking_ids = []
        move_ids = []
        wf_service = netsvc.LocalService("workflow")
        if context is None:
            context = {}

        todo = []
        for move in self.browse(cr, uid, ids, context=context):
            if move.state=="draft":
                todo.append(move.id)
        if todo:
            self.action_confirm(cr, uid, todo, context=context)
            todo = []

        #Do price calculation on moves
        matchresults = self.price_calculation(cr, uid, ids, context=context)
        for move in self.browse(cr, uid, ids, context=context):
            if move.state in ['done','cancel']:
                continue
            move_ids.append(move.id)

            if move.picking_id:
                picking_ids.append(move.picking_id.id)
            if move.move_dest_id.id and (move.state != 'done'):
                # Downstream move should only be triggered if this move is the last pending upstream move
                other_upstream_move_ids = self.search(cr, uid, [('id','!=',move.id),('state','not in',['done','cancel']),
                                            ('move_dest_id','=',move.move_dest_id.id)], context=context)
                if not other_upstream_move_ids:
                    self.write(cr, uid, [move.id], {'move_history_ids': [(4, move.move_dest_id.id)]})
                    if move.move_dest_id.state in ('waiting', 'confirmed'):
                        self.force_assign(cr, uid, [move.move_dest_id.id], context=context)
                        if move.move_dest_id.picking_id:
                            wf_service.trg_write(uid, 'stock.picking', move.move_dest_id.picking_id.id, cr)
                        if move.move_dest_id.auto_validate:
                            self.action_done(cr, uid, [move.move_dest_id.id], context=context)

            self._create_product_valuation_moves(cr, uid, move, move.id in matchresults and matchresults[move.id] or [], context=context)
            if move.state not in ('confirmed','done','assigned'):
                todo.append(move.id)

        if todo:
            self.action_confirm(cr, uid, todo, context=context)

        self.write(cr, uid, move_ids, {'state': 'done', 'date': time.strftime(DEFAULT_SERVER_DATETIME_FORMAT)}, context=context)
        for id in move_ids:
             wf_service.trg_trigger(uid, 'stock.move', id, cr)

        for pick_id in picking_ids:
            wf_service.trg_write(uid, 'stock.picking', pick_id, cr)

        return True


    def _create_account_move_line(self, cr, uid, move, matches, src_account_id, dest_account_id, reference_amount, reference_currency_id, type='', context=None):
        """
        Generate the account.move.line values to post to track the stock valuation difference due to the
        processing of the given stock move.
        """
        move_list = []
        # Consists of access rights 
        # TODO Check if amount_currency is not needed
        match_obj = self.pool.get("stock.move.matching")
        product_obj = self.pool.get('product.product')
        if move.product_id.supply_method =='produce' and type=='out' and move.product_id.cost_method in ['fifo', 'lifo']:
            if move.product_id.cost_method == 'fifo':
                order = 'date, id'
            else: 
                order = 'date desc, id desc'
            matching_obj = self.pool.get('stock.mrp.matching')
            match_obj = self.pool.get('stock.move.matching')
            tuples = []
            match_ids = matching_obj.search(cr, uid, [('product_id','=',move.product_id.id), ('mrp_qty','>',0),('move_out_id','=',False)], order=order)
            product_qty = move.product_qty
            move_list = {}
            for match in matching_obj.browse(cr, uid, match_ids):
                if product_qty <= 0:
                    break
                if match.mrp_qty <= product_qty:
                    matching_obj.write(cr, uid, match.id, {'mrp_qty':  product_qty - match.mrp_qty})
                    if match.price_unit_mrp in move_list:
                        move_list[match.price_unit_mrp] += product_qty
                    else:
                        move_list[match.price_unit_mrp] = product_qty
                    tuples.append((match.move_in_id.id, product_qty, match.price_unit_mrp))
                    product_qty = product_qty - match.mrp_qty
                elif match.qty > product_qty:
                    matching_obj.write(cr, uid, match.id, {'mrp_qty': match.mrp_qty - product_qty})
                    tuples.append((match.move_in_id.id, product_qty, match.price_unit_mrp))
                    product_qty = 0
                    if match.price_unit_mrp in move_list:
                        move_list[match.price_unit_mrp] += match.mrp_qty
                    else:
                        move_list[match.price_unit_mrp] = match.mrp_qty
            if move_list:
                move_list = [ (qty, price * qty) for price, qty in move_list.items()]
            else:
                move_list = [(move.product_qty, move.product_qty * move.price_unit)]
        elif type == 'out' and move.product_id.cost_method in ['fifo', 'lifo']:
            for match in match_obj.browse(cr, uid, matches, context=context):
                move_list += [(match.qty, match.qty * match.price_unit_out)]
        elif move.production_id and type == 'in' and move.product_id.cost_method in ['fifo', 'lifo']:
            new_move_list, product_id, components, product_toconsume= {}, [], {}, {}
            if move.production_id.picking_id:
                for line in move.production_id.bom_id.bom_lines:
                    product_toconsume.update({line.product_id.id: line.product_qty})
                for component in move.production_id.picking_id.move_lines:
                    out_ids = match_obj.search(cr, uid, [ ('move_out_id', '=', component.move_dest_id.id)],context=context)
                    components[component.product_id.id] = [ [out.qty, out.price_unit] for out in match_obj.browse(cr, uid, out_ids) ]
                    product_id.append(component.product_id.id)

            looplen = move.product_qty.is_integer() and int(move.product_qty) or int(move.product_qty+ 1)
            for loop in range(looplen):
                move_price = 0
                for product, stock in components.items():
                    qty, price = product_toconsume[product], 0
                    for i in range(len(stock)):
                        if qty == 0:
                            break
                        if stock[i][0] == 0:
                            continue
                        if stock[i][0] >= qty:
                            price += qty * stock[i][1]
                            stock[i][0] -= qty
                            qty = 0
                        else:
                            price += stock[i][1] * stock[i][0]
                            qty -= stock[i][0]
                            stock[i][0] = 0
                        
                    move_price += price
                if move_price in new_move_list:
                    new_move_list[move_price] += 1
                else:
                    new_move_list[move_price] = 1
            move_list = [ (qty, price * qty) for price, qty in new_move_list.items()]
            new_price = 0
            product_obj = self.pool.get('product.product')
            matching_obj = self.pool.get('stock.mrp.matching')
            for price, qty in new_move_list.items():
                matchvals = {'move_in_id': move.id, 'price_unit_mrp': price,
                           'product_id': move.product_id.id, 'mrp_qty': qty}
                match_id = matching_obj.create(cr, uid, matchvals, context=context)
                new_price += price * qty
            product_obj.write(cr, uid, [move.product_id.id], {'standard_price': new_price / move.product_qty,}, context)
            self.write(cr, uid, move.id, {'price_unit': new_price / move.product_qty}, context=context)
        elif type == 'in' and move.product_id.cost_method in ['fifo', 'lifo']:
            move_list = [(move.product_qty, reference_amount)]
        else:
            move_list = [(move.product_qty, reference_amount)]

        res = []
        for item in move_list:
            # prepare default values considering that the destination accounts have the reference_currency_id as their main currency
            partner_id = (move.picking_id.partner_id and self.pool.get('res.partner')._find_accounting_partner(move.picking_id.partner_id).id) or False
            debit_line_vals = {
                        'name': move.name,
                        'product_id': move.product_id and move.product_id.id or False,
                        'quantity': item[0],
                        'product_uom_id': move.product_uom.id, 
                        'ref': move.picking_id and move.picking_id.name or False,
                        'date': time.strftime('%Y-%m-%d'),
                        'partner_id': partner_id,
                        'debit': item[1],
                        'account_id': dest_account_id,
            }
            credit_line_vals = {
                        'name': move.name,
                        'product_id': move.product_id and move.product_id.id or False,
                        'quantity': item[0],
                        'product_uom_id': move.product_uom.id, 
                        'ref': move.picking_id and move.picking_id.name or False,
                        'date': time.strftime('%Y-%m-%d'),
                        'partner_id': partner_id,
                        'credit': item[1],
                        'account_id': src_account_id,
            }
            res += [(0, 0, debit_line_vals), (0, 0, credit_line_vals)]
        return res

    def _generate_negative_stock_matchings(self, cr, uid, ids, product, context=None):
        """
        This method generates the stock move matches for out moves of product with qty remaining
        according to the in move
        force_company should be in context already
        | ids : id of in move
        | product: browse record of product
        Returns: 
        | List of matches
        """
        assert len(ids) == 1, _("Only generate negative stock matchings one by one")
        move = self.browse(cr, uid, ids, context=context)[0]
        cost_method = product.cost_method
        matching_obj = self.pool.get("stock.move.matching")
        product_obj = self.pool.get("product.product")
        uom_obj = self.pool.get("product.uom")
        res = []
        #Search for the most recent out moves
        moves = self.search(cr, uid, [('company_id', '=', move.company_id.id), ('state','=', 'done'), ('location_id.usage','=','internal'), ('location_dest_id.usage', '!=', 'internal'), 
                                          ('product_id', '=', move.product_id.id), ('qty_remaining', '>', 0.0)], order='date, id', context=context)
        qty_to_go = move.product_qty
        for out_mov in self.browse(cr, uid, moves, context=context):
            if qty_to_go <= 0.0:
                break
            out_qty_converted =  uom_obj._compute_qty(cr, uid, out_mov.product_uom.id, out_mov.qty_remaining, move.product_uom.id, round=False)
            qty = 0.0
            if out_qty_converted <= qty_to_go:
                qty = out_qty_converted
            elif qty_to_go > 0.0: 
                qty = qty_to_go
            revert_qty = (qty / out_qty_converted) * out_mov.qty_remaining
            matchvals = {'move_in_id': move.id, 'qty': revert_qty, 
                         'move_out_id': out_mov.id}
            match_id = matching_obj.create(cr, uid, matchvals, context=context)
            res.append(match_id)
            qty_to_go -= qty
            #Need to re-calculate total price of every out_move if FIFO/LIFO
            if cost_method in ['fifo', 'lifo']:
                matches = matching_obj.search(cr, uid, [('move_out_id', '=', out_mov.id)], context=context)
                amount = 0.0
                total_price = 0.0
                for match in matching_obj.browse(cr, uid, matches, context=context):
                    amount += match.qty 
                    total_price += match.qty * match.price_unit_out
                if amount > 0.0:
                    self.write(cr, uid, [out_mov.id], {'price_unit': total_price / amount}, context=context)
                    if amount >= out_mov.product_qty:
                        product_obj.write(cr, uid, [product.id], {'standard_price': total_price / amount}, context=context)
        return res

    def price_calculation(self, cr, uid, ids, context=None):
        '''
        This method puts the right price on the stock move, 
        adapts the price on the product when necessary
        and creates the necessary stock move matchings
        
        It returns a list of tuples with (move_id, match_id) 
        which is used for generating the accounting entries when FIFO/LIFO
        '''
        product_obj = self.pool.get('product.product')
        currency_obj = self.pool.get('res.currency')
        matching_obj = self.pool.get('stock.move.matching')
        uom_obj = self.pool.get('product.uom')
        
        product_avail = {}
        res = {}
        for move in self.browse(cr, uid, ids, context=context):
            # Initialize variables
            res[move.id] = []
            move_qty = move.product_qty
            move_uom = move.product_uom.id
            company_id = move.company_id.id
            ctx = context.copy()
            user = self.pool.get('res.users').browse(cr, uid, uid, context=context)
            ctx['force_company'] = move.company_id.id
            product = product_obj.browse(cr, uid, move.product_id.id, context=ctx)
            cost_method = product.cost_method
            product_uom_qty = uom_obj._compute_qty(cr, uid, move_uom, move_qty, product.uom_id.id, round=False)
            if not product.id in product_avail:
                product_avail[product.id] = product.qty_available
            
            # Check if out -> do stock move matchings and if fifo/lifo -> update price
            # only update the cost price on the product form on stock moves of type == 'out' because if a valuation has to be made without PO, 
            # for inventories for example we want to use the last value used for an outgoing move
            if move.location_id.usage == 'internal' and move.location_dest_id.usage != 'internal':
                fifo = (cost_method != 'lifo')
                tuples = product_obj.get_stock_matchings_fifolifo(cr, uid, [product.id], move_qty, fifo, 
                                                                  move_uom, move.company_id.currency_id.id, context=ctx) #TODO Would be better to use price_currency_id for migration?
                price_amount = 0.0
                amount = 0.0
                #Write stock matchings
                for match in tuples: 
                    matchvals = {'move_in_id': match[0], 'qty': match[1], 
                                 'move_out_id': move.id}
                    match_id = matching_obj.create(cr, uid, matchvals, context=context)
                    res[move.id].append(match_id)
                    price_amount += match[1] * match[2]
                    amount += match[1]
                #Write price on out move
                if product_avail[product.id] >= product_uom_qty and product.cost_method in ['fifo', 'lifo']:
                    if amount > 0:
                        self.write(cr, uid, move.id, {'price_unit': price_amount / amount}, context=context)
                        product_obj.write(cr, uid, product.id, {'standard_price': price_amount / product_uom_qty}, context=ctx)
                    else:
                        raise osv.except_osv(_('Error'), _("Something went wrong finding stock moves ") + str(tuples) + str(self.search(cr, uid, [('company_id','=', company_id), ('qty_remaining', '>', 0), ('state', '=', 'done'), 
                                             ('location_id.usage', '!=', 'internal'), ('location_dest_id.usage', '=', 'internal'), ('product_id', '=', product.id)], 
                                       order = 'date, id', context=context)) + str(move_qty) + str(move_uom) + str(move.company_id.currency_id.id))
                else:
                    new_price = uom_obj._compute_price(cr, uid, product.uom_id.id, product.standard_price, move_uom)
                    self.write(cr, uid, move.id, {'price_unit': new_price}, context=ctx)
                #Adjust product_avail when not average and move returned from
                if (not move.move_returned_from or product.cost_method != 'average'):
                    product_avail[product.id] -= product_uom_qty
            
            #Check if in => if price 0.0, take standard price / Update price when average price and price on move != standard price
            if move.location_id.usage != 'internal' and move.location_dest_id.usage == 'internal':
                if move.price_unit == 0.0:
                    new_price = uom_obj._compute_price(cr, uid, product.uom_id.id, product.standard_price, move_uom)
                    self.write(cr, uid, move.id, {'price_unit': new_price}, context=ctx)
                elif product.cost_method == 'average':
                    move_product_price = uom_obj._compute_price(cr, uid, move_uom, move.price_unit, product.uom_id.id)
                    if product_avail[product.id] > 0.0:
                        amount_unit = product.standard_price
                        new_std_price = ((amount_unit * product_avail[product.id])\
                                + (move_product_price * product_uom_qty))/(product_avail[product.id] + product_uom_qty)
                    else:
                        new_std_price = move_product_price
                    product_obj.write(cr, uid, [product.id], {'standard_price': new_std_price}, context=ctx)
                # Should create the stock move matchings for previous outs for the negative stock that can be matched with is in
                if product_avail[product.id] < 0.0:
                    resneg = self._generate_negative_stock_matchings(cr, uid, [move.id], product, context=ctx)
                    res[move.id] += resneg
                product_avail[product.id] += product_uom_qty
            #The return of average products at average price (could be made optional)
            if move.location_id.usage == 'internal' and move.location_dest_id.usage != 'internal' and cost_method == 'average' and move.move_returned_from:
                move_orig = move.move_returned_from
                new_price = uom_obj._compute_price(cr, uid, move_orig.product_uom, move_orig.price_unit, product.uom_id.id)
                if (product_avail[product.id]- product_uom_qty) >= 0.0:
                    amount_unit = product.standard_price
                    new_std_price = ((amount_unit * product_avail[product.id])\
                                     - (new_price * product_uom_qty))/(product_avail[product.id] - product_uom_qty)
                    self.write(cr, uid, [move.id],{'price_unit': move_orig.price_unit,})
                    product_obj.write(cr, uid, [product.id], {'standard_price': new_std_price}, context=ctx)
                product_avail[product.id] -= product_uom_qty
        return res

    # FIXME: needs refactoring, this code is partially duplicated in stock_picking.do_partial()!
    def do_partial(self, cr, uid, ids, partial_datas, context=None):
        """ Makes partial pickings and moves done.
        @param partial_datas: Dictionary containing details of partial picking
                          like partner_id, delivery_date, delivery
                          moves with product_id, product_qty, uom
        """
        res = {}
        picking_obj = self.pool.get('stock.picking')
        product_obj = self.pool.get('product.product')
        currency_obj = self.pool.get('res.currency')
        uom_obj = self.pool.get('product.uom')
        wf_service = netsvc.LocalService("workflow")

        if context is None:
            context = {}

        complete, too_many, too_few = [], [], []
        move_product_qty, prodlot_ids, partial_qty, product_uoms = {}, {}, {}, {}
        for move in self.browse(cr, uid, ids, context=context):
            if move.state in ('done', 'cancel'):
                continue
            partial_data = partial_datas.get('move%s'%(move.id), {})
            product_qty = partial_data.get('product_qty',0.0)
            move_product_qty[move.id] = product_qty
            product_uom = partial_data.get('product_uom',False)
            product_price = partial_data.get('product_price',0.0)
            product_currency = partial_data.get('product_currency',False)
            prodlot_id = partial_data.get('prodlot_id')
            prodlot_ids[move.id] = prodlot_id
            product_uoms[move.id] = product_uom
            partial_qty[move.id] = uom_obj._compute_qty(cr, uid, product_uoms[move.id], product_qty, move.product_uom.id)
            if move.product_qty == partial_qty[move.id]:
                complete.append(move)
            elif move.product_qty > partial_qty[move.id]:
                too_few.append(move)
            else:
                too_many.append(move)

        for move in too_few:
            product_qty = move_product_qty[move.id]
            if product_qty != 0:
                defaults = {
                            'product_qty' : product_qty,
                            'product_uos_qty': product_qty,
                            'picking_id' : move.picking_id.id,
                            'state': 'assigned',
                            'move_dest_id': False,
                            'price_unit': product_price,
                            }
                prodlot_id = prodlot_ids[move.id]
                if prodlot_id:
                    defaults.update(prodlot_id=prodlot_id)
                new_move = self.copy(cr, uid, move.id, defaults)
                complete.append(self.browse(cr, uid, new_move))
            self.write(cr, uid, [move.id],
                    {
                        'product_qty': move.product_qty - product_qty,
                        'product_uos_qty': move.product_qty - product_qty,
                        'prodlot_id': False,
                        'tracking_id': False,
                    })


        for move in too_many:
            self.write(cr, uid, [move.id],
                    {
                        'product_qty': move.product_qty,
                        'product_uos_qty': move.product_qty,
                    })
            complete.append(move)

        for move in complete:
            if prodlot_ids.get(move.id):
                self.write(cr, uid, [move.id],{'prodlot_id': prodlot_ids.get(move.id)})
            self.action_done(cr, uid, [move.id], context=context)
            if  move.picking_id.id :
                # TOCHECK : Done picking if all moves are done
                cr.execute("""
                    SELECT move.id FROM stock_picking pick
                    RIGHT JOIN stock_move move ON move.picking_id = pick.id AND move.state = %s
                    WHERE pick.id = %s""",
                            ('done', move.picking_id.id))
                res = cr.fetchall()
                if len(res) == len(move.picking_id.move_lines):
                    picking_obj.action_move(cr, uid, [move.picking_id.id])
                    wf_service.trg_validate(uid, 'stock.picking', move.picking_id.id, 'button_done', cr)

        return [move.id for move in complete]
Example #33
0
class ids_employee_exit(osv.Model):

    _name = 'ids.employee.exit'
    _description = 'Employee Full &amp; Final'
    _inherit = ['mail.thread', 'ir.needaction_mixin']

    _columns = {
        'fnf_number':
        fields.char('F&F Number', size=15, readonly=True),
        'employee_id':
        fields.many2one(
            'hr.employee',
            'Employee Name',
            required=True,
            domain=
            "['|',('working_status', '=', 'resigned'),('working_status', '=', 'exit')]"
        ),
        'job_id':
        fields.related('employee_id',
                       'job_id',
                       type='many2one',
                       relation='hr.job',
                       string='Job Position',
                       store=True,
                       readonly=True),
        'department_id':
        fields.related('employee_id',
                       'department_id',
                       type='many2one',
                       relation='hr.department',
                       string='Department',
                       store=True,
                       readonly=True),
        'joining_date':
        fields.related('employee_id',
                       'joining_date',
                       type='date',
                       relation='hr.employee',
                       string='Joining Date',
                       store=True,
                       readonly=True),
        'confirmation_status':
        fields.related('employee_id',
                       'confirmation_status',
                       type='char',
                       relation='hr.employee',
                       string='Employee status',
                       store=True,
                       readonly=True),
        'resign_id':
        fields.many2one('ids.hr.employee.separation', 'Resign ID'),
        'nodues_id':
        fields.many2one('emp.no.dues', 'No Dues ID'),
        'capture_date':
        fields.related('resign_id',
                       'capture_date',
                       type='date',
                       relation='ids.hr.employee.separation',
                       string='Resignation Date ',
                       store=True),
        'last_date':
        fields.related('resign_id',
                       'last_date',
                       type='date',
                       relation='ids.hr.employee.separation',
                       string='Last Working Day',
                       store=True),
        'dob':
        fields.related('employee_id',
                       'birthday',
                       type='char',
                       relation='hr.employee',
                       string='Date Of Birth',
                       store=True,
                       readonly=True),
        'division_id':
        fields.related('employee_id',
                       'division',
                       type='many2one',
                       relation='division',
                       string='Division',
                       store=True,
                       readonly=True),
        'location_id':
        fields.related('employee_id',
                       'office_location',
                       type='many2one',
                       relation='office.location',
                       string='Location',
                       store=True,
                       readonly=True),
        'gender':
        fields.related('employee_id',
                       'gender',
                       type='char',
                       relation='hr.employee',
                       string='Gender',
                       store=True,
                       readonly=True),
        'mobile_no':
        fields.related('employee_id',
                       'mobile_phone',
                       type='char',
                       relation='hr.employee',
                       string='Mobile No',
                       store=True,
                       readonly=True),
        'state':
        fields.selection([('draft', 'Draft'), ('phase1', 'Phase-1'),
                          ('phase2', 'Phase-2'), ('phase3', 'Phase-3'),
                          ('completed', 'Completed')],
                         'Status',
                         readonly=True),

        #Leave Details Columns
        'leave_detail_ids':
        fields.one2many('ids.employee.ff.leave',
                        'fullfinal_id',
                        'Leave Details',
                        readonly=True,
                        store=True,
                        ondelete="cascade"),
        #Notice Period Details Columns
        'np_required':
        fields.selection([('yes', 'Yes'), ('no', 'No'), ('na', 'N/A')],
                         'Notice Period Required',
                         required=True),
        'reason_no':
        fields.text('Reason For No'),
        'shortfall':
        fields.float('Shortfall in Notice Period(Days)'),
        'shortfall_reason':
        fields.text('Reasons for shortfall'),
        #Gratuity Details Columns
        'last_wages':
        fields.float('Amount of wages last claimed'),
        'service_period':
        fields.char('Total period of service'),
        'eligibility':
        fields.selection([('yes', 'Yes'), ('no', 'No')],
                         'Eligibility',
                         required=True),
        'gratuity_years':
        fields.integer('Gratuity Years'),
        'amount_claimed':
        fields.float('Amount of gratuity claimed'),
        #Agreement Details Columns
        'service_agreement':
        fields.selection([('yes', 'Yes'), ('no', 'No')],
                         'Service Agreement',
                         required=True),
        'start_date':
        fields.date('Start Date'),
        'end_date':
        fields.date('End Date'),
        'recoverable_applicable':
        fields.selection([('yes', 'Yes'), ('no', 'No')],
                         'Recoverable Applicable',
                         required=True),
        'amount':
        fields.float('Amount'),
        'valid_date':
        fields.date('Valid Date'),
        #Attendance Details Columns
        'last_month_days':
        fields.float('25th to 30th/31th of previous month(Days)'),
        'cur_month_days':
        fields.float('1st till last working day(Days)'),
        #Bonus Information Columns
        'bonus':
        fields.selection([('yes', 'Yes'), ('no', 'No')],
                         'Bonus',
                         required=True),
        'bonus_amount':
        fields.float('Amount'),
        'lta':
        fields.selection([('yes', 'Yes'), ('no', 'No')], 'LTA', required=True),
        'lta_amount':
        fields.float('Amount'),
        'loyalty':
        fields.selection([('yes', 'Yes'), ('no', 'No')],
                         'Loyalty',
                         required=True),
        'loyalty_amount':
        fields.float('Amount'),
        #Allowance Details Columns
        'night_allow':
        fields.float('Night Allowance'),
        'night_month':
        fields.selection([('1', 'January'), ('2', 'February'), ('3', 'March'),
                          ('4', 'April'), ('5', 'May'), ('6', 'June'),
                          ('7', 'July'), ('8', 'August'), ('9', 'September'),
                          ('10', 'October'), ('11', 'November'),
                          ('12', 'December')], 'Month'),
        'ot_allow':
        fields.float('Overtime Allowance'),
        'ot_month':
        fields.selection([('1', 'January'), ('2', 'February'), ('3', 'March'),
                          ('4', 'April'), ('5', 'May'), ('6', 'June'),
                          ('7', 'July'), ('8', 'August'), ('9', 'September'),
                          ('10', 'October'), ('11', 'November'),
                          ('12', 'December')], 'Month'),
        'attendance_allow':
        fields.float('Attendance Allowance'),
        'attendance_month':
        fields.selection([('1', 'January'), ('2', 'February'), ('3', 'March'),
                          ('4', 'April'), ('5', 'May'), ('6', 'June'),
                          ('7', 'July'), ('8', 'August'), ('9', 'September'),
                          ('10', 'October'), ('11', 'November'),
                          ('12', 'December')], 'Month'),
        'prod_incentive':
        fields.float('Production Incentive'),
        'incentive_month':
        fields.selection([('1', 'January'), ('2', 'February'), ('3', 'March'),
                          ('4', 'April'), ('5', 'May'), ('6', 'June'),
                          ('7', 'July'), ('8', 'August'), ('9', 'September'),
                          ('10', 'October'), ('11', 'November'),
                          ('12', 'December')], 'Month'),
        #No Dues Details Columns(Facility)
        'icard_return':
        fields.selection([('yes', 'Yes'), ('no', 'No'), ('na', 'N/A')],
                         'I-Card Return',
                         required=True),
        'access_card_return':
        fields.selection([('yes', 'Yes'), ('no', 'No'), ('na', 'N/A')],
                         'Access Card Return',
                         required=True),
        'keys_return':
        fields.selection([('yes', 'Yes'), ('no', 'No'), ('na', 'N/A')],
                         'Keys Return',
                         required=True),
        'headphone_return':
        fields.selection([('yes', 'Yes'), ('no', 'No'), ('na', 'N/A')],
                         'Head Phone Return',
                         required=True),
        'name_delete':
        fields.selection([('yes', 'Yes'), ('no', 'No'), ('na', 'N/A')],
                         'Name delete from attendance Registers',
                         required=True),
        'canteen_dues':
        fields.selection([('yes', 'Yes'), ('no', 'No'), ('na', 'N/A')],
                         'Canteen dues Cleared',
                         required=True),
        'library_book':
        fields.selection([('yes', 'Yes'), ('no', 'No'), ('na', 'N/A')],
                         'Library Books Return',
                         required=True),
        'remarks':
        fields.char('Remarks'),
        'submitted_by_facility':
        fields.many2one('res.users', 'Submitted By'),
        'submitted_on_facility':
        fields.datetime('Submitted On'),

        #No Dues Details Columns(Operation)
        'email_control':
        fields.char('Email Control'),
        'email_remarks':
        fields.char('Remarks'),
        'internet_control':
        fields.char('Internet Control'),
        'internet_remarks':
        fields.char('Remarks'),
        'remote_control':
        fields.char('Remote Control'),
        'remote_remarks':
        fields.char('Remarks'),
        'software_requirement':
        fields.char('Software Requirement'),
        'software_remarks':
        fields.char('Remarks'),
        'application_share':
        fields.char('Application Share Access'),
        'application_remarks':
        fields.char('Remarks'),
        'data_backup':
        fields.char('Databack-up Details'),
        'data_backup_remarks':
        fields.char('Remarks'),
        'handover_takeover':
        fields.selection([('yes', 'Yes'), ('no', 'No'), ('na', 'N/A')],
                         'Handover Takeover Done',
                         required=True),
        'handover_remarks':
        fields.char('Remarks(if any items not return)'),
        'submitted_by_operation':
        fields.many2one('res.users', 'Submitted By'),
        'submitted_on_operation':
        fields.datetime('Submitted On'),

        #No Dues Details Columns(Technical)
        'login_name_tech':
        fields.char('Login Name'),
        'login_name_disable':
        fields.selection([('yes', 'Yes'), ('no', 'No'), ('na', 'N/A')],
                         'Disable'),
        'login_remarks_tech':
        fields.char('User-Name Remarks'),
        'allocation_it_asset':
        fields.selection([('yes', 'Yes'), ('no', 'No'), ('na', 'N/A')],
                         'Allocation of IT Assets'),
        'it_assets_disable':
        fields.selection([('yes', 'Yes'), ('no', 'No'), ('na', 'N/A')],
                         'Disable'),
        'asset_remarks_tech':
        fields.char('Asset Remarks'),
        'email_id_tech':
        fields.selection([('yes', 'Yes'), ('no', 'No'), ('na', 'N/A')],
                         'Email ID Created'),
        'email_id_disable':
        fields.selection([('yes', 'Yes'), ('no', 'No'), ('na', 'N/A')],
                         'Disable'),
        'email_remarks_tech':
        fields.char('Email Remarks'),
        'internet_control_tech':
        fields.selection([('yes', 'Yes'), ('no', 'No'), ('na', 'N/A')],
                         'Internet Access Control'),
        'internal_disable':
        fields.selection([('yes', 'Yes'), ('no', 'No'), ('na', 'N/A')],
                         'Disable'),
        'internet_remarks_tech':
        fields.char('Internet Remarks'),
        'backup_setup_tech':
        fields.selection([('yes', 'Yes'), ('no', 'No'), ('na', 'N/A')],
                         'Back-Up Setup'),
        'backup_setup_disable':
        fields.selection([('yes', 'Yes'), ('no', 'No'), ('na', 'N/A')],
                         'Disable'),
        'backup_remarks_tech':
        fields.char('Back-up Remarks'),
        'software_requirement_tech':
        fields.selection([('yes', 'Yes'), ('no', 'No'), ('na', 'N/A')],
                         'Software Provisioning and Access Control'),
        'software_disable':
        fields.selection([('yes', 'Yes'), ('no', 'No'), ('na', 'N/A')],
                         'Disable'),
        'software_remarks_tech':
        fields.char('Software Provisioning Remarks'),
        'application_share_tech':
        fields.selection([('yes', 'Yes'), ('no', 'No'), ('na', 'N/A')],
                         'Application Share Access'),
        'appliaction_share_disable':
        fields.selection([('yes', 'Yes'), ('no', 'No'), ('na', 'N/A')],
                         'Disable'),
        'application_remarks_tech':
        fields.char('Share Access Remarks'),
        'submitted_by_technical':
        fields.many2one('res.users', 'Submitted By'),
        'submitted_on_technical':
        fields.datetime('Submitted On'),

        # Remarks Column
        'group_hr_remarks':
        fields.text('Group HR Remarks'),
        'group_head_remarks':
        fields.text('Group Head Remarks'),
        'corp_hr_remarks':
        fields.text('Corp HR Remarks'),
        'hr_head_remarks':
        fields.text('HR Head Remarks'),
        'image_sign':
        fields.binary(
            "Sign",
            help=
            "This field holds the image used as sign, limited to 1024x1024px."
        ),
    }
    _rec_name = 'fnf_number'

    _defaults = {
        'state': 'draft',
        'capture_date': fields.date.context_today,
    }

    def create(self, cr, uid, vals, context=None):
        """Create the unique id """
        vals['fnf_number'] = self.pool.get('ir.sequence').get(
            cr, uid, 'ids.employee.exit')
        res = super(ids_employee_exit, self).create(cr, uid, vals)
        return res

    def unlink(self, cr, uid, ids, context=None):
        for rec in self.browse(cr, uid, ids, context=context):
            if rec.state not in ['draft']:
                raise osv.except_osv(
                    _('Warning!'),
                    _('You cannot delete a full and final entry which is not in draft state.'
                      ))
        return super(ids_employee_exit, self).unlink(cr, uid, ids, context)

    def submit_draft(self, cr, uid, ids, context=None):
        """Draft Submit. """
        return self.write(cr, uid, ids, {'state': 'phase1'})

    def submit_phase1(self, cr, uid, ids, context=None):
        """PHASE-1 Submit. """
        return self.write(cr, uid, ids, {'state': 'phase2'})

    def cancel_phase1(self, cr, uid, ids, context=None):
        """PHASE-1 Cancel. """
        return self.write(cr, uid, ids, {'state': 'draft'})

    def submit_phase2(self, cr, uid, ids, context=None):
        """PHASE-2 Submit. """
        return self.write(cr, uid, ids, {'state': 'phase3'})

    def submit_phase3(self, cr, uid, ids, context=None):
        """PHASE-3 Submit. """
        return self.write(cr, uid, ids, {'state': 'completed'})

    def cancel_phase3(self, cr, uid, ids, context=None):
        """PHASE-3 Cancel. """
        return self.write(cr, uid, ids, {'state': 'phase2'})

    def _calculate_years_between_two_dates(self,
                                           cr,
                                           uid,
                                           ids,
                                           start_date,
                                           end_date,
                                           context=None):
        d1 = datetime.strptime(start_date, DEFAULT_SERVER_DATE_FORMAT).date()
        d2 = datetime.strptime(end_date, DEFAULT_SERVER_DATE_FORMAT).date()
        r = relativedelta(d2, d1)
        year = str(r.years)
        month = str(r.months)
        day = str(r.days)
        service_period = year + ' years,' + month + ' month,' + day + ' days'
        gt_years = r.years
        if r.months > 5:
            gt_years = r.years + 1
        return service_period, gt_years

    def onchange_last_wages(self,
                            cr,
                            uid,
                            ids,
                            last_wages,
                            eligibility,
                            gratuity_years,
                            context=None):
        res = {'value': {'amount_claimed': False}}
        if eligibility == 'yes':
            res['value']['amount_claimed'] = (gratuity_years * last_wages *
                                              15) / 26
        else:
            res['value']['amount_claimed'] = 0
        return res

    def calculate_shortfall(self,
                            cr,
                            uid,
                            ids,
                            employee_id,
                            np_required,
                            capture_date,
                            last_date,
                            context=None):
        shortfall = 0
        if np_required == 'yes':
            notice_period_days = 0
            if employee_id:
                employee = self.pool.get('hr.employee').browse(
                    cr, uid, employee_id)
                notice_period_days = int(employee.notice)
            last = datetime.strptime(
                capture_date, "%Y-%m-%d") + timedelta(days=notice_period_days)
            shortfall = (last - datetime.strptime(last_date, "%Y-%m-%d")).days
        return {'value': {'shortfall': shortfall}}

    def onchange_employee(self, cr, uid, ids, employee_id, context=None):
        res = {
            'value': {
                'job_id': False,
                'department_id': False,
                'joining_date': False,
                'confirmation_status': False,
                'resign_id': False,
                'capture_date': False,
                'last_date': False,
                'nodues_id': False,
            }
        }

        joining_date = ''
        last_date = ''

        if employee_id:
            exit_ids = self.search(cr,
                                   uid, [('employee_id', '=', employee_id)],
                                   context=context)
            if len(exit_ids) > 0:
                raise osv.except_osv(
                    _('Warning!'),
                    _('Full & Final has already been in progress/done for this employee.'
                      ))

            ee = self.pool.get('hr.employee').browse(cr,
                                                     uid,
                                                     employee_id,
                                                     context=context)
            if ee:
                notice_period_days = int(ee.notice)
                if notice_period_days > 0:
                    res['value']['np_required'] = 'yes'
                res['value']['job_id'] = ee.job_id.id
                res['value']['department_id'] = ee.department_id.id
                res['value']['dob'] = ee.birthday
                res['value']['division_id'] = ee.division.id
                res['value']['location_id'] = ee.office_location.id
                res['value']['gender'] = ee.gender
                res['value']['mobile_no'] = ee.mobile_phone
                joining_date = res['value']['joining_date'] = ee.joining_date
                res['value'][
                    'confirmation_status'] = ee.confirmation_status.title()
                emp_ff_leave_obj = self.pool.get('ids.employee.ff.leave')
                leave_ids = emp_ff_leave_obj._get_leave_details(cr,
                                                                uid,
                                                                ids,
                                                                employee_id,
                                                                context=None)
                res['value']['leave_detail_ids'] = leave_ids
                if ee.service_agreement == True:
                    res['value']['service_agreement'] = 'yes'
                    res['value']['start_date'] = ee.agreement_start_date
                    res['value']['end_date'] = ee.agreement_end_date
                else:
                    res['value']['service_agreement'] = 'no'

            emp_sep_id = self.pool.get('ids.hr.employee.separation').search(
                cr,
                uid, [('employee_id', '=', employee_id),
                      ('state', '=', 'done')],
                context=context)
            if emp_sep_id:
                es = self.pool.get('ids.hr.employee.separation').browse(
                    cr, uid, emp_sep_id[0], context=context)
                if es:
                    res['value']['resign_id'] = es.id
                    res['value']['capture_date'] = es.capture_date
                    last_date = res['value']['last_date'] = es.last_date
            emp_contract = self.pool.get('hr.contract').search(
                cr, uid, [('employee_id', '=', employee_id)], context=context)
            if emp_contract:
                ec = self.pool.get('hr.contract').browse(cr,
                                                         uid,
                                                         emp_contract[0],
                                                         context=context)
                if ec:
                    res['value']['last_wages'] = ec.basic

            emp_nodues_id = self.pool.get('emp.no.dues').search(
                cr, uid, [('employee_id', '=', employee_id)], context=context)
            if emp_nodues_id:
                en = self.pool.get('emp.no.dues').browse(cr,
                                                         uid,
                                                         emp_nodues_id[0],
                                                         context=context)
                if en:
                    res['value']['nodues_id'] = en.id
                    res['value']['icard_return'] = en.icard_return
                    res['value']['access_card_return'] = en.access_card_return
                    res['value']['keys_return'] = en.keys_return
                    res['value']['headphone_return'] = en.headphone_return
                    res['value']['name_delete'] = en.name_delete
                    res['value']['canteen_dues'] = en.canteen_dues
                    res['value']['library_book'] = en.library_book
                    res['value']['remarks'] = en.remarks
                    res['value'][
                        'submitted_by_facility'] = en.submitted_by_facility
                    res['value'][
                        'submitted_on_facility'] = en.submitted_on_facility

                    res['value']['email_control'] = en.email_control
                    res['value']['email_remarks'] = en.email_remarks
                    res['value']['internet_control'] = en.internet_control
                    res['value']['internet_remarks'] = en.internet_remarks
                    res['value']['remote_control'] = en.remote_control
                    res['value']['remote_remarks'] = en.remote_remarks
                    res['value'][
                        'software_requirement'] = en.software_requirement
                    res['value']['software_remarks'] = en.software_remarks
                    res['value']['application_share'] = en.application_share
                    res['value'][
                        'application_remarks'] = en.application_remarks
                    res['value']['data_backup'] = en.data_backup
                    res['value'][
                        'data_backup_remarks'] = en.data_backup_remarks
                    res['value']['handover_takeover'] = en.handover_takeover
                    res['value']['handover_remarks'] = en.handover_remarks
                    res['value'][
                        'submitted_by_operation'] = en.submitted_by_operation
                    res['value'][
                        'submitted_on_operation'] = en.submitted_on_operation

                    res['value']['login_name_tech'] = en.login_name_tech
                    res['value']['login_name_disable'] = en.login_name_disable
                    res['value']['login_remarks_tech'] = en.login_remarks_tech
                    res['value'][
                        'allocation_it_asset'] = en.allocation_it_asset
                    res['value']['it_assets_disable'] = en.it_assets_disable
                    res['value']['asset_remarks_tech'] = en.asset_remarks_tech
                    res['value']['email_id_tech'] = en.email_id_tech
                    res['value']['email_id_disable'] = en.email_id_disable
                    res['value']['email_remarks_tech'] = en.email_remarks_tech
                    res['value'][
                        'internet_control_tech'] = en.internet_control_tech
                    res['value']['internal_disable'] = en.internal_disable
                    res['value'][
                        'internet_remarks_tech'] = en.internet_remarks_tech
                    res['value']['backup_setup_tech'] = en.backup_setup_tech
                    res['value'][
                        'backup_setup_disable'] = en.backup_setup_disable
                    res['value'][
                        'backup_remarks_tech'] = en.backup_remarks_tech
                    res['value'][
                        'software_requirement_tech'] = en.software_requirement_tech
                    res['value']['software_disable'] = en.software_disable
                    res['value'][
                        'software_remarks_tech'] = en.software_remarks_tech
                    res['value'][
                        'application_share_tech'] = en.application_share_tech
                    res['value'][
                        'appliaction_share_disable'] = en.appliaction_share_disable
                    res['value'][
                        'application_remarks_tech'] = en.application_remarks_tech
                    res['value'][
                        'submitted_by_technical'] = en.submitted_by_technical
                    res['value'][
                        'submitted_on_technical'] = en.submitted_on_technical

            if (joining_date and last_date):
                res['value'][
                    'gratuity_years'] = self._calculate_years_between_two_dates(
                        cr, uid, ids, joining_date, last_date, context=None)[1]
                res['value'][
                    'service_period'] = self._calculate_years_between_two_dates(
                        cr, uid, ids, joining_date, last_date, context=None)[0]
        return res
    #                     asset_lines_obj.write(cr, uid, asset_line.get('id'), {'move_check': True, 'move_id': created_id})
    #                     logging.getLogger(self._name).info("""account.move.line created for {0}""".format(asset_name))
    #                 except:
    #                     logging.getLogger('account.asset.asset').error(
    #                         """ERROR creating the entries of
    #                         account move from {0}.""".format(__name__))
    #                     raise orm.except_orm('Error', 'Failure creating the'
    #                         ' account move lines.')
    #
    #             #else:
    #             #    logging.getLogger(self._name).info("Este activo ya esta asentado!")


    _columns = {
    'department_id' : fields.many2one('hr.department', 'Departament'),
    'life_expectancy' : fields.float('Life Expectancy', help="""Life expectancy
     of the asset in years."""),
    'life_expectancy_percentage': fields.float('Life Expectancy Percentage'),
    'stage_id': fields.many2one('account.asset.stage', 'Stage',
        help="""The stage of the asset indicate in wich point of his life is
        at the moment. You can add new stages in configuration."""),
    'code': fields.char("Code", size=9, required=True),
    'model_id': fields.many2one('account.asset.model', 'Model'),
    'brand_id': fields.related('model_id', 'brand_id', string='Brand',
        type="many2one", relation="account.asset.model", readonly=True),
    'category': fields.selection((
        ('administrative', 'Administrative'),
        ('scholarly', 'Scholarly'),
        ('none', 'None')), 'Type of asset', help="""The type of
    asset, scholarly or administrative."""),
    'asset_move_ids': fields.one2many('account.asset.move', 'asset_id',
        'Movements')
Example #35
0
class crm_opportunity_report(osv.Model):
    """ CRM Opportunity Analysis """
    _name = "crm.opportunity.report"
    _auto = False
    _description = "CRM Opportunity Analysis"
    _rec_name = 'date_deadline'

    _columns = {
        'date_deadline':
        fields.date('Expected Closing', readonly=True),
        'create_date':
        fields.datetime('Creation Date', readonly=True),
        'opening_date':
        fields.datetime('Assignation Date', readonly=True),
        'date_closed':
        fields.datetime('Close Date', readonly=True),
        'date_last_stage_update':
        fields.datetime('Last Stage Update', readonly=True),
        'active':
        fields.boolean('Active', readonly=True),

        # durations
        'delay_open':
        fields.float('Delay to Assign',
                     digits=(16, 2),
                     readonly=True,
                     group_operator="avg",
                     help="Number of Days to open the case"),
        'delay_close':
        fields.float('Delay to Close',
                     digits=(16, 2),
                     readonly=True,
                     group_operator="avg",
                     help="Number of Days to close the case"),
        'delay_expected':
        fields.float('Overpassed Deadline',
                     digits=(16, 2),
                     readonly=True,
                     group_operator="avg"),
        'user_id':
        fields.many2one('res.users', 'User', readonly=True),
        'team_id':
        fields.many2one('crm.team',
                        'Sales Team',
                        oldname='section_id',
                        readonly=True),
        'nbr_activities':
        fields.integer('# of Activities', readonly=True),
        'city':
        fields.char('City'),
        'country_id':
        fields.many2one('res.country', 'Country', readonly=True),
        'company_id':
        fields.many2one('res.company', 'Company', readonly=True),
        'probability':
        fields.float('Probability',
                     digits=(16, 2),
                     readonly=True,
                     group_operator="avg"),
        'total_revenue':
        fields.float('Total Revenue', digits=(16, 2), readonly=True),
        'expected_revenue':
        fields.float('Expected Revenue', digits=(16, 2), readonly=True),
        'stage_id':
        fields.many2one(
            'crm.stage',
            'Stage',
            readonly=True,
            domain="['|', ('team_id', '=', False), ('team_id', '=', team_id)]"
        ),
        'stage_name':
        fields.char('Stage Name', readonly=True),
        'partner_id':
        fields.many2one('res.partner', 'Partner', readonly=True),
        'company_id':
        fields.many2one('res.company', 'Company', readonly=True),
        'priority':
        fields.selection(crm_stage.AVAILABLE_PRIORITIES, 'Priority'),
        'type':
        fields.selection(
            [
                ('lead', 'Lead'),
                ('opportunity', 'Opportunity'),
            ],
            'Type',
            help="Type is used to separate Leads and Opportunities"),
        'lost_reason':
        fields.many2one('crm.lost.reason', 'Lost Reason', readonly=True),
        'date_conversion':
        fields.datetime('Conversion Date', readonly=True),
        'campaign_id':
        fields.many2one('utm.campaign', 'Campaign', readonly=True),
        'source_id':
        fields.many2one('utm.source', 'Source', readonly=True),
        'medium_id':
        fields.many2one('utm.medium', 'Medium', readonly=True),
    }

    def init(self, cr):
        tools.drop_view_if_exists(cr, 'crm_opportunity_report')
        cr.execute("""
            CREATE OR REPLACE VIEW crm_opportunity_report AS (
                SELECT
                    c.id,
                    c.date_deadline,

                    c.date_open as opening_date,
                    c.date_closed as date_closed,
                    c.date_last_stage_update as date_last_stage_update,

                    c.user_id,
                    c.probability,
                    c.stage_id,
                    stage.name as stage_name,
                    c.type,
                    c.company_id,
                    c.priority,
                    c.team_id,
                    (SELECT COUNT(*)
                     FROM mail_message m
                     WHERE m.model = 'crm.lead' and m.res_id = c.id) as nbr_activity,
                    c.active,
                    c.campaign_id,
                    c.source_id,
                    c.medium_id,
                    c.partner_id,
                    c.city,
                    c.country_id,
                    c.planned_revenue as total_revenue,
                    c.planned_revenue*(c.probability/100) as expected_revenue,
                    c.create_date as create_date,
                    extract('epoch' from (c.date_closed-c.create_date))/(3600*24) as  delay_close,
                    abs(extract('epoch' from (c.date_deadline - c.date_closed))/(3600*24)) as  delay_expected,
                    extract('epoch' from (c.date_open-c.create_date))/(3600*24) as  delay_open,
                    c.lost_reason,
                    c.date_conversion as date_conversion
                FROM
                    "crm_lead" c
                LEFT JOIN "crm_stage" stage
                ON stage.id = c.stage_id
                GROUP BY c.id, stage.name
            )""")
Example #36
0
    _columns = {
        'checklist_task_id': fields.many2one('checklist.task', 'Checklist Task', required=True, ondelete='cascade'),
        'checklist_id': fields.related('checklist_task_id', 'checklist_id', type='many2one', relation='checklist', string='Checklist'),
        'model_id': fields.related('checklist_id', 'model_id', type='many2one', relation='ir.model', string='Model'),
        'name': fields.related('checklist_task_id', 'name', type='char', size=128, string='Name'),
        'mandatory': fields.related('checklist_task_id', 'mandatory', type='boolean', string='Mandatory', help='Required to make active object'),
        'res_id': fields.integer('Resource ID', select=True, required=True),
        'active': fields.function(_get_activity, type='boolean', string='Active', store=False, multi='activity'),
        'sequence': fields.function(_get_activity, type='integer', string='Priority', store={
            'checklist.task': (_get_checklist_task_instance_ids, ['sequence'], 10),
        }, multi='activity'),
        'field_ids_to_fill': fields.function(_get_activity, type='one2many', relation='checklist.task.field',
                                             string='Fields to fill', store=False, multi='activity'),
        'field_ids_filled': fields.function(_get_activity, type='one2many', relation='checklist.task.field',
                                            string='Filled fields', store=False, multi='activity'),
        'progress_rate': fields.float('Progress Rate', digits=(16, 2)),
    }

    _defaults = {
        'progress_rate': 0.0,
        'sequence': 15,
    }


class ChecklistException(osv.osv):
    _name = 'checklist.exception'
    _description = 'Checklist Exception'
    _rec_name = 'checklist_task_id'
    _order = "create_date desc"

    def ChecklistExceptionEmail(self, cr, uid, company_id, method, checklist_task_id, object_id, action_id, exception, stack):
class product_scale_system_product_line(Model):
    _name = 'product.scale.system.product.line'
    _order = 'scale_system_id, sequence'

    _TYPE_SELECTION = [
        ('id', 'Product ID'),
        ('numeric', 'Numeric Field'),
        ('text', 'Char / Text Field'),
        ('external_text', 'External Text Field'),
        ('constant', 'Constant Value'),
        ('external_constant', 'External Constant Text Value'),
        ('many2one', 'ManyOne Field'),
        ('many2many', 'Many2Many Field'),
        ('product_image', 'Product Image'),
    ]

    # Column Section
    _columns = {
        'scale_system_id': fields.many2one(
            'product.scale.system', 'Scale System', required=True,
            ondelete='cascade', select=True),
        'company_id': fields.related(
            'scale_system_id', 'company_id', type='many2one', string='Company',
            relation='res.company', store=True),
        'code': fields.char(string='Bizerba Code', required=True),
        'name': fields.char(string='Name', required=True),
        'sequence': fields.integer(string='Sequence', required=True),
        'type': fields.selection(
            _TYPE_SELECTION, string='Type'),
        'field_id': fields.many2one(
            'ir.model.fields', string='Product Field', domain="["
            "('model', 'in', ['product.product', 'product.template'])]"),
        # TODO Improve. Set domain, depending on the other field
        'related_field_id': fields.many2one(
            'ir.model.fields', string='M2M / M2O Field', help="Used only"
            " for the x2x fields. Set here the field of the related model"
            " that you want to send to the scale. Let empty to send the ID."),
        'x2many_range': fields.integer(
            string='range of the x2Many Fields', help="Used if type is"
            " 'Many2Many Field', to mention the"
            " range of the field  to send. Begin by 0. (used for exemple"
            " for product logos)"),
        'constant_value': fields.char(
            string='Constant Value', help="Used if type is 'constant',"
            " to send allways the same value."),
        'multiline_length': fields.integer(
            string='Length for Multiline',
            help="Used if type is 'Text Field' or 'External Text Constant'"
            ", to indicate the max length of a line. Set 0 to avoid to split"
            " the value."),
        'multiline_separator': fields.char(
            string='Separator for Multiline', help="Used if type is"
            " 'Text Field' or 'External Text Constant', to indicate wich text"
            " will be used to mention break lines."),
        # TODO Improve. Set contrains.
        'suffix': fields.char(
            string='Suffix', help="Used if type is"
            " 'External Text Field', to indicate how to suffix the field.\n"
            " Make sure to have a uniq value by Scale System, and all with the"
            " same size.\n\n Used if type is Product Image to mention the end"
            " of the file. Exemple : '_01.jpg'."),
        'numeric_coefficient': fields.float(
            string='Numeric Coefficient', help="Used if type is"
            " 'Numeric Field', to mention with coefficient numeric"
            " field should be multiplyed."),
        'numeric_round': fields.float(
            string='Rounding Method', help="Used if type is"
            " 'Numeric Field', to mention how the value should be rounded.\n"
            " Do not Use 0, because it will truncate the value."),
        'delimiter': fields.char(
            string='Delimiter Char', help="Used to finish the column"),
    }

    _defaults = {
        'sequence': 10,
        'multiline_length': 0,
        'multiline_separator': '\n',
        'numeric_coefficient': 1,
        'numeric_round': 1,
        'delimiter': '#',
    }
import time

from openerp.osv import orm, fields
from openerp.addons import decimal_precision as dp
from .res_company import COMPANY_FISCAL_TYPE, COMPANY_FISCAL_TYPE_DEFAULT

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 = {
Example #39
0
    def fields_view_get(self, cr, uid, view_id=None, view_type='form', context=None, toolbar=False, submenu=False):
        result = super(product_search_ept, self).fields_view_get(cr, uid, view_id, view_type, context, toolbar,submenu)
        if context is None:
            context={}
        self._columns = {}
        self._columns['product_ids'] = fields.text('Product IDS')
        if view_type != 'form':
            return result
        _moves_arch_lst = """
            <form string="Stone Search" version="7.0">
                  <div>
        """
        #_moves_arch_lst += """<group colspan="4" col="10">"""
        _line_fields = result['fields']
        info = [
                    {'model':None,'_column_name':'product_name','label':'Stone ID','type':'char','name':'name','product_search_type':'char'},
                    {'model':None,'_column_name':'product_certificate_no','label':'Certificate No.','type':'char','name':'certificate_no','product_search_type':'char'},
                    {'model':None,'_column_name':'product_weight','label':'Weight','no':3,'type':'float','name':'weight','product_search_type':'char','range':True},
                    {'model':None,'_column_name':'product_price_caret','label':'PPC','no':1,'type':'float','name':'price_caret','product_search_type':'char','range':True},
                    {'model':None,'_column_name':'product_discount','label':'Back%','no':1,'type':'float','name':'discount','product_search_type':'char','range':True},
                    {'model':'product.shape','width':'15%','_column_name':'product_shape','label':'SHP','help':'Shape','type':'many2one','name':'shape_id','product_search_type':'boolean','on_change':'product_shape_change'}, 
                    {'model':'product.color','width':'8%','_column_name':'product_color','label':'CLR','help':'Color','type':'many2one','name':'color_id','product_search_type':'boolean','on_change':'product_color_change'},
                    {'model':'product.clarity','width':'10%','_column_name':'product_clarity','label':'CLRTY','help':'Clarity','type':'many2one','name':'clarity_id','product_search_type':'boolean','on_change':'product_clarity_change'},
                    {'model':'product.cut','width':'12%','_column_name':'product_cut','label':'CUT','help':'Cut','type':'many2one','name':'cut_id','product_search_type':'boolean','on_change':'product_cut_change'},
                    {'model':'product.polish','width':'8%','_column_name':'product_polish','label':'POL','help':'Polish','type':'many2one','name':'polish_id','product_search_type':'boolean','on_change':'product_polish_change'},
                    {'model':'product.symmetry','width':'10%','_column_name':'product_symmetry','label':'SYM','help':'Symmetry','type':'many2one','name':'symmetry_id','product_search_type':'boolean','on_change':'product_symmetry_change'},
                    {'model':'product.fluorescence.intensity','width':'13%','_column_name':'product_fluorescence_intensity','label':'FLUR','help':'Fluorescence Intensity','type':'many2one','name':'fluorescence_intensity_id','product_search_type':'boolean','on_change':'product_fluorescence_intensity_change'},
                    {'model':'product.lab','width':'8%','_column_name':'product_lab','label':'LAB','help':'Lab','type':'many2one','name':'lab_id','product_search_type':'boolean','on_change':'product_lab_change'},
                    {'model':'product.fancy.color','width':'15%','_column_name':'product_fancy_color','label':'FNC CLR','help':'Fancy Color','type':'many2one','name':'fancy_color_id','product_search_type':'boolean','on_change':'product_fancy_color_change'},
                    {'model':'product.fancy.color.intensity','width':'15%','_column_name':'product1_fancy_color_intensity','label':'FNC CLR INT','help':'Fancy Color Intensity','type':'many2one','name':'fancy_color_intensity','product_search_type':'boolean','on_change':'product1_fancy_color_intensity_change'},
                    {'model':'product.fancy.color.overtone','width':'15%','_column_name':'product2_fancy_color_overtone','label':'FNC CLR OVR','help':'Fancy Color Overtone','type':'many2one','name':'fancy_color_overtone','product_search_type':'boolean','on_change':'product2_fancy_color_overtone_change'},
                    {'model':None,'_column_name':'product_status','width':'20%','label':'Status','type':'selection','name':'product_status','product_search_type':'boolean'
                              ,'selection_val':[('available','Available'),
                                                ('hold','Hold'),
                                                ('sold','Sold'),
                                               ('on_approval','On Approval'),
                                                ('on_consignment','On Consignment'),
                                                ('offline','Offline'),
                                                ('repair','Repair'),
                                                ('web_sale','Web Sale')]},
                    {'model':'stock.location','_column_name':'stock_location','width':'15%','label':'Location','type':'many2one','name':'location_id','product_search_type':'boolean'
                                    ,'domain':[('usage','=','internal')],},
                ]

        for model_info in info :        
            if model_info['type'] == 'many2one' and model_info['product_search_type'] == 'boolean' :
                if model_info['model']:
                    ids = self.pool.get(model_info['model']).search(cr,uid,model_info.get('domain',[]))
                    if ids :
                        _moves_arch_lst += """<div style="float:left;width:%s;">"""%(model_info.get('width', '100%'))
                        ''' Header '''
                        if model_info.get('label', False)=='Location':
                            _moves_arch_lst += """<u><label style="color:rgb(124,123,173);font-weight:bold;" string="%s"/></u>"""%(model_info['label'])
                        if model_info.get('on_change', False):
                            ''' Check box for Select All '''
                            _moves_arch_lst += """<div><field name="%s"  class="oe_inline"  
                                                         nolabel="1" 
                                                         on_change="%s(%s)"/>
                                                         """%(model_info['on_change'],model_info['on_change'],model_info['on_change'])
                            ''' Label for Select All '''                  
                            _moves_arch_lst += """<u><label help='%s' style="color:rgb(124, 123, 173);" string="%s" for="%s" /></u></div>"""%(model_info['help'],model_info['label'],model_info['label']) 
                            _line_fields.update({
                             '%s'%(model_info['on_change']) : {
                                 'string': 'All ?',
                                 'type' : 'boolean',
                            },})  
                            self._columns['%s'%(model_info['on_change'])] = fields.boolean(model_info['on_change'])                
                        for obj in self.pool.get(model_info['model']).browse(cr,uid,ids,context=context):
                            name=len(obj.name) > 7 and (obj.name[:7]+'...') or obj.name[:7]
                            _line_fields.update({
                             '%s%s'%(model_info['_column_name'],obj.id) : {
                                 'string': obj.name,
                                 'type' : 'boolean',
                                 'help' : '%s'%(obj.name)
                             },})
                            self._columns['%s%s'%(model_info['_column_name'],obj.id)] = fields.boolean(obj.name)
                        
                            ''' Check box and related label '''
                            _moves_arch_lst += """
                                 <div><field name="%s%s" class="oe_inline" nolabel="1"/>
                                 <label string="%s" for="%s%s" /></div>
                                 """%(model_info['_column_name'],obj.id,name,model_info['_column_name'],obj.id)

                        _moves_arch_lst += """</div>"""           
#######################            
            if model_info['type'] == 'char' and model_info['product_search_type'] == 'char':
                _moves_arch_lst += """<div style="width:%s;float:left;">""" %('50%')
                _line_fields.update({
                             '%s'%(model_info['_column_name']) : {
                                 'string': 'Name',
                                 'type' : 'char',
                                 'help' : '%s'%(model_info['_column_name']),
                             },})
                self._columns['%s'%(model_info['_column_name'])] = fields.char(model_info['label'],size=1024)
                _moves_arch_lst += """
                                <div>
                                    <label style="color:rgb(124, 123, 173);" string="%s" for="%s" />
                                    <field name="%s" style="width: 70%%"  nolabel="1"/>
                                </div>
                                </div>
                                 """%(model_info['label'],model_info['_column_name'],model_info['_column_name'])
  
################################
            if model_info['type'] == 'selection' and model_info['product_search_type'] == 'boolean' :
                if model_info['selection_val']:
                    _moves_arch_lst += """<div style="float:left;width:%s">"""%(model_info['width'])
                    _moves_arch_lst += """<u><label style="color:rgb(124, 123, 173);font-weight:bold;" string="%s" /></u><newline/>"""%(model_info['label'])
                    for value in model_info['selection_val']:
                        _line_fields.update({
                         '%s_%s'%(model_info['_column_name'],value[0]) : {
                             'string': value[1],
                             'type' : 'boolean',
                         },})
                        self._columns['%s_%s'%(model_info['_column_name'],value[0])] = fields.boolean(value[1])
                        _moves_arch_lst += """
                             <div><field name="%s_%s" nolabel="1"/>
                             <label string="%s" for="%s_%s" /></div>
                             """%(model_info['_column_name'],value[0],value[1],model_info['_column_name'],value[0])
                    _moves_arch_lst +="""</div>"""
###########################                        
            if model_info.get('range') and model_info['range']:
                width = '50%'
                if model_info.get('no') > 1:width = '100%'
                _moves_arch_lst += """<div style="float:left;width:%s;">"""%(width)
                _moves_arch_lst += """<div style="float:left;width:%s;"><label style="color:rgb(124, 123, 173);font-weight:bold;" string="%s" /></div>"""%('15%',model_info['label'])
                if model_info.get('no'):
                    no = model_info.get('no')
                    wid = str(85/int(no)) + '%'
                    while no != 0 :
                         
                        no = no - 1
                        _line_fields.update({'%s_from_%s'%(model_info['_column_name'],no) : {'string': model_info['label'],'type':'float'}})
                        _line_fields.update({'%s_to_%s'%(model_info['_column_name'],no) : {'string': model_info['label'],'type':'float'}})
                        self._columns['%s_from_%s'%(model_info['_column_name'],no)] = fields.float(model_info['label'],digits=(16,2))
                        self._columns['%s_to_%s'%(model_info['_column_name'],no)] = fields.float(model_info['label'],digits=(16,2))
                        _moves_arch_lst += """
                                        <div style="float:left;width:%s;"> 
                                             
                                             <div style="float:left;"><field name="%s_from_%s" placeholder="From" class="oe_inline" nolabel="1"/></div>
                                             <div style="float:left;"><b><label style="color:rgb(124, 123, 173);" string="--" /></b></div>
                                             <div style="float:left;"><field name="%s_to_%s" placeholder="To" class="oe_inline" nolabel="1"/></div>
                                             
                                        </div> 
                                     """%(wid,model_info['_column_name'],no,model_info['_column_name'],no)
                _moves_arch_lst += """</div>"""         
        _moves_arch_lst += """ 
                            </div>
                          <footer>
                          <button name="get_product" string="Search" type="object" colspan="2" class="oe_highlight"/>
                             or
                         <button string="Cancel" class="oe_link" special="cancel"/>
                          </footer>
                          </form>
                 """

        result['arch'] = _moves_arch_lst
        result['arch'] = result['arch'].replace('&','&amp;')
        result['fields'] = _line_fields
        return result       
Example #40
0
class buying_postage(osv.osv_memory):
    _name = "buying.postage"
    _description = "Buying Postage"

    def action_buy_postge(self, cr, uid, ids, context=None):        
        ship_endicia = self.pool.get('shipping.endicia').get_endicia_info(cr,uid,context)
        requester_id = ship_endicia.requester_id
        account_id = ship_endicia.account_id
        passphrase = ship_endicia.passphrase
        debug = ship_endicia.test
        tot_rate = self.browse(cr,uid,ids[0]).name
        if tot_rate < 10.00:
            raise osv.except_osv(_('Error'), _('You cannot buy postage less than $10'))
        try:
            request = endicia.RecreditRequest(requester_id, account_id, passphrase, tot_rate, debug=debug)
            response = request.send()
            buy_postage_resp = response._get_value()            
        except Exception, e:
            raise osv.except_osv(_('Error'), _('Error buying postage'))
        message = _('Remaining postage balance: %s\nTotal amount of postage printed: %s' % (buy_postage_resp['postage_balance'], buy_postage_resp['postage_printed']))
        self.log(cr, uid, ids[0], message)
        return {'type': 'ir.actions.act_window_close'}


    _columns = {
        'name': fields.float('Total Rate'),
    }

buying_postage()
Example #41
0
            
                 
            #res[company.id]['smart_cash'] = 0.0
        return res

    _columns = {
       'smart_budget': fields.function(_smart_cash, type="float", digits_compute=dp.get_precision('Account'), string='SMart Budget',multi='all',help="Approved invoiced amount.",),
#       'smart_cash': fields.function(smart_cash, type="float", digits_compute=dp.get_precision('Account'), string='SMart Budget',
#            help="Approved invoiced amount.",
#            multi='all',),
       'smart_cash': fields.function(_smart_cash, type="float", digits_compute=dp.get_precision('Account'), string='SMart Cash',
            help="Free invoiced amount for salary or expenses.",
            multi='all',),
        'prepayment': fields.boolean('Prepayment',help="SMart User: this virtual company can have prepayment smart_cash, SMart Company: this country applies prepayment"),
        'prepayment_days': fields.integer('Prepayment Days',help="Leadtime in days before invoiced amount becomes smart_cash (global)"),
        'smart_share': fields.float('SMarts Share',digits_compute=dp.get_precision('Account')),
        'sale_order_sum_cash': fields.function(_smart_cash, type="float", digits_compute=dp.get_precision('Account'), string='SMart Order sum cash',multi='all',help="Approved invoiced amount.",),
        'sale_order_sum_budget':fields.function(_smart_cash, type="float", digits_compute=dp.get_precision('Account'), string='SMart Order sum budget',multi='all',help="Approved invoiced amount.",),
        'smart_amount_cash':fields.function(_smart_cash, type="float", digits_compute=dp.get_precision('Account'), string='SMart Amount cash',multi='all',help="Approved invoiced amount.",),
        'smart_amount_budget':fields.function(_smart_cash, type="float", digits_compute=dp.get_precision('Account'), string='SMart Amount budget',multi='all',help="Approved invoiced amount.",),
        'activity_amount_cash':fields.function(_smart_cash, type="float", digits_compute=dp.get_precision('Account'), string='SMart activity amount cash',multi='all',help="Approved invoiced amount.",),
        'activity_amount_budget':fields.function(_smart_cash, type="float", digits_compute=dp.get_precision('Account'), string='SMart activity amount budget',multi='all',help="Approved invoiced amount.",),
        'expense_sum_cash':fields.function(_smart_cash, type="float", digits_compute=dp.get_precision('Account'), string='SMart expense sum cash',multi='all',help="Approved invoiced amount.",),
        'expense_sum_budget':fields.function(_smart_cash, type="float", digits_compute=dp.get_precision('Account'), string='SMart expense sum budget',multi='all',help="Approved invoiced amount.",),
    }

    _defaults = {
        'prepayment': True,
        'smart_cash': 0.0,
        'smart_budget': 0.0,
    }
Example #42
0
                help="Computed as: Time Spent + Remaining Time.",
                store={
                    'project.task': (lambda self, cr, uid, ids, c={}: ids,
                        ['work_ids', 'remaining_hours', 'planned_hours'], 10),
                    'project.task.work': (_get_task, ['hours'], 10),
                }),
        'progress': fields.function(_hours_get, method=True,
                string='Progress (%)',
                multi='hours',
                group_operator="avg",
                help="Computed as: Time Spent / Total Time.",
                store={
                    'project.task': (lambda self, cr, uid, ids, c={}: ids,
                        ['work_ids', 'remaining_hours', 'planned_hours',
                         'state'], 10),
                    'project.task.work': (_get_task, ['hours'], 10),
                }),
        'delay_hours': fields.function(_hours_get, method=True,
                string='Delay Hours', multi='hours',
                help="Computed as difference of the time estimated by the\
                        project manager and the real time to close the task.",
                store={
                    'project.task': (lambda self, cr, uid, ids, c={}: ids,
                        ['work_ids', 'remaining_hours', 'planned_hours'], 10),
                    'project.task.work': (_get_task, ['hours'], 10),
                }),
        'cost_per_task': fields.float('Cost', readonly=True,
                help="Computed as: Hour Cost multiplied by Job Hours"),

    }
Example #43
0
                cr, uid, line.taxes_id, line.price, line.qty, line.product_id, line.back_order_id.partner_id
            )
            cur = line.back_order_id.pricelist_id.currency_id
            res[line.id] = cur_obj.round(cr, uid, cur, taxes["total"])
        return res

    def _get_uom_id(self, cr, uid, context=None):
        try:
            proxy = self.pool.get("ir.model.data")
            result = proxy.get_object_reference(cr, uid, "product", "product_uom_unit")
            return result[1]
        except Exception, ex:
            return False

    _columns = {
        #        'location_destination_id': fields.many2one('stock.location', 'Stock Destination Location'),
        #        'location_id': fields.many2one('stock.location', 'Stock Source Location'),
        "product_id": fields.many2one("product.product", "Product"),
        "back_order_id": fields.many2one("back.to.back.order", "Back Order"),
        "qty": fields.float("Quantity"),
        "price": fields.float("Unit Price"),
        "subtotal": fields.function(_amount_line, string="Subtotal", digits_compute=dp.get_precision("Account")),
        "taxes_id": fields.many2many("account.tax", "purchase_order_taxe", "ord_id", "tax_id", "Taxes"),
        "product_uom": fields.many2one("product.uom", "Product Unit of Measure", required=True),
    }

    _defaults = {"product_uom": _get_uom_id}


# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
Example #44
0
class crm_claim(orm.Model):
    _inherit = 'crm.claim'

    _columns = {
        'number':
        fields.char('Number',
                    size=128,
                    readonly=True,
                    states={'draft': [('readonly', False)]},
                    required=True,
                    help="Company internal claim unique number"),
        'claim_type':
        fields.selection(
            [('customer', 'Customer'), ('supplier', 'Supplier'),
             ('other', 'Other')],
            'Claim type',
            required=True,
            help=
            "customer = from customer to company ; supplier = from company to supplier"
        ),
        'claim_line_ids':
        fields.one2many('claim.line', 'claim_id', 'Return lines'),
        'product_exchange_ids':
        fields.one2many('product.exchange', 'claim_return_id',
                        'Product exchanges'),
        # Aftersale outsourcing
        #        'in_supplier_picking_id': fields.many2one('stock.picking', 'Return To Supplier Picking', required=False, select=True),
        #        'out_supplier_picking_id': fields.many2one('stock.picking', 'Return From Supplier Picking', required=False, select=True),

        # Financial management
        'planned_revenue':
        fields.float('Expected revenue'),
        'planned_cost':
        fields.float('Expected cost'),
        'real_revenue':
        fields.float('Real revenue'),
        'real_cost':
        fields.float('Real cost'),
        'invoice_ids':
        fields.one2many('account.invoice', 'claim_id', 'Refunds'),
        'picking_ids':
        fields.one2many('stock.picking', 'claim_id', 'RMA'),
        'invoice_id':
        fields.many2one('account.invoice', 'Invoice', help='Related invoice'),
        'warehouse_id':
        fields.many2one('stock.warehouse', 'Warehouse', required=True),
    }
    _defaults = {
        'number':
        lambda obj, cr, uid, context: obj.pool.get('ir.sequence').get(
            cr, uid, 'crm.claim'),
        'claim_type':
        lambda *a: 'customer',
        'warehouse_id':
        lambda *a: 1,
    }

    def onchange_partner_address_id(self,
                                    cr,
                                    uid,
                                    ids,
                                    add,
                                    email=False,
                                    context=None):
        res = super(crm_claim, self).onchange_partner_address_id(cr,
                                                                 uid,
                                                                 ids,
                                                                 add,
                                                                 email=email)
        if add:
            if not res['value']['email_from'] or not res['value'][
                    'partner_phone']:
                address = self.pool.get('res.partner').browse(cr, uid, add)
                for other_add in address.partner_id.address:
                    if other_add.email and not res['value']['email_from']:
                        res['value']['email_from'] = other_add.email
                    if other_add.phone and not res['value']['partner_phone']:
                        res['value']['partner_phone'] = other_add.phone
        return res

    def onchange_invoice_id(self, cr, uid, ids, invoice_id, context=None):
        invoice_line_obj = self.pool.get('account.invoice.line')
        invoice_line_ids = invoice_line_obj.search(
            cr, uid, [('invoice_id', '=', invoice_id)])
        claim_lines = []
        for invoice_line in invoice_line_obj.browse(cr, uid, invoice_line_ids):
            #            claim_line_obj = self.pool.get('claim.line')
            claim_lines.append({
                'name': invoice_line.name,
                'claim_origine': "none",
                'invoice_line_id': invoice_line.id,
                'product_id': invoice_line.product_id.id,
                'product_returned_quantity': invoice_line.quantity,
                'unit_sale_price': invoice_line.price_unit,
                #                    'prodlot_id' : invoice_line.,
                'state': 'draft',
            })
#            for line in claim_line_obj.browse(cr,uid,[line_id],context):
#                line.set_warranty()
        return {'value': {'claim_line_ids': claim_lines}}
Example #45
0
class PaymentAcquirer(osv.Model):
    """ Acquirer Model. Each specific acquirer can extend the model by adding
    its own fields, using the acquirer_name as a prefix for the new fields.
    Using the required_if_provider='<name>' attribute on fields it is possible
    to have required fields that depend on a specific acquirer.

    Each acquirer has a link to an ir.ui.view record that is a template of
    a button used to display the payment form. See examples in ``payment_ogone``
    and ``payment_paypal`` modules.

    Methods that should be added in an acquirer-specific implementation:

     - ``<name>_form_generate_values(self, cr, uid, id, reference, amount, currency,
       partner_id=False, partner_values=None, tx_custom_values=None, context=None)``:
       method that generates the values used to render the form button template.
     - ``<name>_get_form_action_url(self, cr, uid, id, context=None):``: method
       that returns the url of the button form. It is used for example in
       ecommerce application, if you want to post some data to the acquirer.
     - ``<name>_compute_fees(self, cr, uid, id, amount, currency_id, country_id,
       context=None)``: computed the fees of the acquirer, using generic fields
       defined on the acquirer model (see fields definition).

    Each acquirer should also define controllers to handle communication between
    OpenERP and the acquirer. It generally consists in return urls given to the
    button form and that the acquirer uses to send the customer back after the
    transaction, with transaction details given as a POST request.
    """
    _name = 'payment.acquirer'
    _description = 'Payment Acquirer'
    _order = 'sequence'

    def _get_providers(self, cr, uid, context=None):
        return []

    # indirection to ease inheritance
    _provider_selection = lambda self, *args, **kwargs: self._get_providers(*args, **kwargs)

    _columns = {
        'name': fields.char('Name', required=True),
        'provider': fields.selection(_provider_selection, string='Provider', required=True),
        'company_id': fields.many2one('res.company', 'Company', required=True),
        'pre_msg': fields.html('Message', translate=True,
            help='Message displayed to explain and help the payment process.'),
        'post_msg': fields.html('Thanks Message', help='Message displayed after having done the payment process.'),
        'validation': fields.selection(
            [('manual', 'Manual'), ('automatic', 'Automatic')],
            string='Process Method',
            help='Static payments are payments like transfer, that require manual steps.'),
        'view_template_id': fields.many2one('ir.ui.view', 'Form Button Template', required=True),
        'environment': fields.selection(
            [('test', 'Test'), ('prod', 'Production')],
            string='Environment', oldname='env'),
        'website_published': fields.boolean(
            'Visible in Portal / Website', copy=False,
            help="Make this payment acquirer available (Customer invoices, etc.)"),
        'auto_confirm': fields.selection(
            [('none', 'No automatic confirmation'),
             ('at_pay_confirm', 'At payment confirmation'),
             ('at_pay_now', 'At payment')],
            string='Order Confirmation', required=True),
        # Fees
        'fees_active': fields.boolean('Compute fees'),
        'fees_dom_fixed': fields.float('Fixed domestic fees'),
        'fees_dom_var': fields.float('Variable domestic fees (in percents)'),
        'fees_int_fixed': fields.float('Fixed international fees'),
        'fees_int_var': fields.float('Variable international fees (in percents)'),
        'sequence': fields.integer('Sequence', help="Determine the display order"),
    }

    _defaults = {
        'company_id': lambda self, cr, uid, obj, ctx=None: self.pool['res.users'].browse(cr, uid, uid).company_id.id,
        'environment': 'test',
        'validation': 'automatic',
        'website_published': True,
        'auto_confirm': 'at_pay_confirm',
    }

    def _check_required_if_provider(self, cr, uid, ids, context=None):
        """ If the field has 'required_if_provider="<provider>"' attribute, then it
        required if record.provider is <provider>. """
        for acquirer in self.browse(cr, uid, ids, context=context):
            if any(getattr(f, 'required_if_provider', None) == acquirer.provider and not acquirer[k] for k, f in self._fields.items()):
                return False
        return True

    _constraints = [
        (_check_required_if_provider, 'Required fields not filled', ['required for this provider']),
    ]

    def get_form_action_url(self, cr, uid, id, context=None):
        """ Returns the form action URL, for form-based acquirer implementations. """
        acquirer = self.browse(cr, uid, id, context=context)
        if hasattr(self, '%s_get_form_action_url' % acquirer.provider):
            return getattr(self, '%s_get_form_action_url' % acquirer.provider)(cr, uid, id, context=context)
        return False

    def form_preprocess_values(self, cr, uid, id, reference, amount, currency_id, tx_id, partner_id, partner_values, tx_values, context=None):
        """  Pre process values before giving them to the acquirer-specific render
        methods. Those methods will receive:

             - partner_values: will contain name, lang, email, zip, address, city,
               country_id (int or False), country (browse or False), phone, reference
             - tx_values: will contain reference, amount, currency_id (int or False),
               currency (browse or False), partner (browse or False)
        """
        acquirer = self.browse(cr, uid, id, context=context)

        if tx_id:
            tx = self.pool.get('payment.transaction').browse(cr, uid, tx_id, context=context)
            tx_data = {
                'reference': tx.reference,
                'amount': tx.amount,
                'currency_id': tx.currency_id.id,
                'currency': tx.currency_id,
                'partner': tx.partner_id,
            }
            partner_data = {
                'name': tx.partner_name,
                'lang': tx.partner_lang,
                'email': tx.partner_email,
                'zip': tx.partner_zip,
                'address': tx.partner_address,
                'city': tx.partner_city,
                'country_id': tx.partner_country_id.id,
                'country': tx.partner_country_id,
                'phone': tx.partner_phone,
                'reference': tx.partner_reference,
                'state': None,
            }
        else:
            if partner_id:
                partner = self.pool['res.partner'].browse(cr, uid, partner_id, context=context)
                partner_data = {
                    'name': partner.name,
                    'lang': partner.lang,
                    'email': partner.email,
                    'zip': partner.zip,
                    'city': partner.city,
                    'address': _partner_format_address(partner.street, partner.street2),
                    'country_id': partner.country_id.id,
                    'country': partner.country_id,
                    'phone': partner.phone,
                    'state': partner.state_id,
                }
            else:
                partner, partner_data = False, {}
            partner_data.update(partner_values)

            if currency_id:
                currency = self.pool['res.currency'].browse(cr, uid, currency_id, context=context)
            else:
                currency = self.pool['res.users'].browse(cr, uid, uid, context=context).company_id.currency_id
            tx_data = {
                'reference': reference,
                'amount': amount,
                'currency_id': currency.id,
                'currency': currency,
                'partner': partner,
            }

        # update tx values
        tx_data.update(tx_values)

        # update partner values
        if not partner_data.get('address'):
            partner_data['address'] = _partner_format_address(partner_data.get('street', ''), partner_data.get('street2', ''))
        if not partner_data.get('country') and partner_data.get('country_id'):
            partner_data['country'] = self.pool['res.country'].browse(cr, uid, partner_data.get('country_id'), context=context)
        partner_data.update({
            'first_name': _partner_split_name(partner_data['name'])[0],
            'last_name': _partner_split_name(partner_data['name'])[1],
        })

        # compute fees
        fees_method_name = '%s_compute_fees' % acquirer.provider
        if hasattr(self, fees_method_name):
            fees = getattr(self, fees_method_name)(
                cr, uid, id, tx_data['amount'], tx_data['currency_id'], partner_data['country_id'], context=None)
            tx_data['fees'] = float_round(fees, 2)

        return (partner_data, tx_data)

    def render(self, cr, uid, id, reference, amount, currency_id, tx_id=None, partner_id=False, partner_values=None, tx_values=None, context=None):
        """ Renders the form template of the given acquirer as a qWeb template.
        All templates will receive:

         - acquirer: the payment.acquirer browse record
         - user: the current user browse record
         - currency_id: id of the transaction currency
         - amount: amount of the transaction
         - reference: reference of the transaction
         - partner: the current partner browse record, if any (not necessarily set)
         - partner_values: a dictionary of partner-related values
         - tx_values: a dictionary of transaction related values that depends on
                      the acquirer. Some specific keys should be managed in each
                      provider, depending on the features it offers:

          - 'feedback_url': feedback URL, controler that manage answer of the acquirer
                            (without base url) -> FIXME
          - 'return_url': URL for coming back after payment validation (wihout
                          base url) -> FIXME
          - 'cancel_url': URL if the client cancels the payment -> FIXME
          - 'error_url': URL if there is an issue with the payment -> FIXME

         - context: OpenERP context dictionary

        :param string reference: the transaction reference
        :param float amount: the amount the buyer has to pay
        :param res.currency browse record currency: currency
        :param int tx_id: id of a transaction; if set, bypasses all other given
                          values and only render the already-stored transaction
        :param res.partner browse record partner_id: the buyer
        :param dict partner_values: a dictionary of values for the buyer (see above)
        :param dict tx_custom_values: a dictionary of values for the transction
                                      that is given to the acquirer-specific method
                                      generating the form values
        :param dict context: OpenERP context
        """
        if context is None:
            context = {}
        if tx_values is None:
            tx_values = {}
        if partner_values is None:
            partner_values = {}
        acquirer = self.browse(cr, uid, id, context=context)

        # pre-process values
        amount = float_round(amount, 2)
        partner_values, tx_values = self.form_preprocess_values(
            cr, uid, id, reference, amount, currency_id, tx_id, partner_id,
            partner_values, tx_values, context=context)

        # call <name>_form_generate_values to update the tx dict with acqurier specific values
        cust_method_name = '%s_form_generate_values' % (acquirer.provider)
        if hasattr(self, cust_method_name):
            method = getattr(self, cust_method_name)
            partner_values, tx_values = method(cr, uid, id, partner_values, tx_values, context=context)

        qweb_context = {
            'tx_url': context.get('tx_url', self.get_form_action_url(cr, uid, id, context=context)),
            'submit_class': context.get('submit_class', 'btn btn-link'),
            'submit_txt': context.get('submit_txt'),
            'acquirer': acquirer,
            'user': self.pool.get("res.users").browse(cr, uid, uid, context=context),
            'reference': tx_values['reference'],
            'amount': tx_values['amount'],
            'currency': tx_values['currency'],
            'partner': tx_values.get('partner'),
            'partner_values': partner_values,
            'tx_values': tx_values,
            'context': context,
        }

        # because render accepts view ids but not qweb -> need to use the xml_id
        return self.pool['ir.ui.view'].render(cr, uid, acquirer.view_template_id.xml_id, qweb_context, engine='ir.qweb', context=context)

    def _wrap_payment_block(self, cr, uid, html_block, amount, currency_id, context=None):
        payment_header = _('Pay safely online')
        amount_str = float_repr(amount, self.pool.get('decimal.precision').precision_get(cr, uid, 'Account'))
        currency = self.pool['res.currency'].browse(cr, uid, currency_id, context=context)
        currency_str = currency.symbol or currency.name
        amount = u"%s %s" % ((currency_str, amount_str) if currency.position == 'before' else (amount_str, currency_str))
        result = u"""<div class="payment_acquirers">
                         <div class="payment_header">
                             <div class="payment_amount">%s</div>
                             %s
                         </div>
                         %%s
                     </div>""" % (amount, payment_header)
        return result % html_block.decode("utf-8")

    def render_payment_block(self, cr, uid, reference, amount, currency_id, tx_id=None, partner_id=False, partner_values=None, tx_values=None, company_id=None, context=None):
        html_forms = []
        domain = [('website_published', '=', True), ('validation', '=', 'automatic')]
        if company_id:
            domain.append(('company_id', '=', company_id))
        acquirer_ids = self.search(cr, uid, domain, context=context)
        for acquirer_id in acquirer_ids:
            button = self.render(
                cr, uid, acquirer_id,
                reference, amount, currency_id,
                tx_id, partner_id, partner_values, tx_values,
                context)
            html_forms.append(button)
        if not html_forms:
            return ''
        html_block = '\n'.join(filter(None, html_forms))
        return self._wrap_payment_block(cr, uid, html_block, amount, currency_id, context=context)
Example #46
0
        res = super(account_voucher, self).onchange_amount(cr, uid, ids, amount, rate, partner_id, journal_id, currency_id, ttype, date, payment_rate_currency_id, company_id, context=context)
        res['value'].update({'cc_order_amt':amount, 'cc_refund_amt':amount}) 
        return res

    _inherit = 'account.voucher'
    _columns = {
        'cc_name':fields.char("Card Holder's Name", size=32,),
        'cc_b_addr_1':fields.char('Billing Address1', size=32,),
        'cc_b_addr_2':fields.char('Billing Address2', size=32,),
        'cc_city': fields.char('City', size=32,),
        'cc_state':fields.char('State', size=32,),
        'cc_zip':fields.char('Postal/Zip', size=32,),
        'cc_country':fields.char('Country', size=32,),
        'cc_order_date':fields.date('Order Date',),
<<<<<<< HEAD
        'cc_order_amt':fields.float('Order Amt'),
=======
        'cc_order_amt':fields.float('Order Amt',required=True),
>>>>>>> c1979f64b3360c86d60e00c92be0271d89f97f2d
        'cc_number':fields.char('Credit Card Number', size=256),
        'cc_v':fields.char('Card Code Verification', size=3),
        'cc_e_d_month':fields.char('Expiration Date MM', size=32),
        'cc_e_d_year':fields.char('Expiration Date YY', size=32),
        'cc_comment':fields.char('Comment', size=128,),
        'cc_auth_code':fields.char('Authorization Code', size=32),
        'cc_save_card_details':fields.boolean('Save Credit Card details'),
        'cc_ecommerce_sale':fields.boolean('Ecommerce sale'),
        'cc_p_authorize':fields.boolean('Pre-authorize'),
        'cc_charge':fields.boolean('Charge'),
        'cc_info_hide':fields.boolean('Credit Info Hide'),
        'cc_status':fields.text('Status Message'),
Example #47
0
class claim_line(orm.Model):
    """
    Class to handle a product return line (corresponding to one invoice line)
    """
    _name = "claim.line"
    _description = "List of product to return"

    # Method to calculate total amount of the line : qty*UP
    def _line_total_amount(self, cr, uid, ids, field_name, arg, context=None):
        res = {}
        for line in self.browse(cr, uid, ids):
            res[line.
                id] = line.unit_sale_price * line.product_returned_quantity
        return res

    _columns = {
        'name':
        fields.char('Description', size=64, required=True),
        'claim_origine':
        fields.selection([('none', 'Not specified'),
                          ('legal', 'Legal retractation'),
                          ('cancellation', 'Order cancellation'),
                          ('damaged', 'Damaged delivered product'),
                          ('error', 'Shipping error'),
                          ('exchange', 'Exchange request'),
                          ('lost', 'Lost during transport'),
                          ('other', 'Other')],
                         'Claim Subject',
                         required=True,
                         help="To describe the line product problem"),
        'claim_descr':
        fields.text('Claim description',
                    help="More precise description of the problem"),
        'product_id':
        fields.many2one('product.product', 'Product', help="Returned product"),
        'product_returned_quantity':
        fields.float('Quantity',
                     digits=(12, 2),
                     help="Quantity of product returned"),
        'unit_sale_price':
        fields.float(
            'Unit sale price',
            digits=(12, 2),
            help=
            "Unit sale price of the product. Auto filed if retrun done by invoice selection. BE CAREFUL AND CHECK the automatic value as don't take into account previous refounds, invoice discount, can be for 0 if product for free,..."
        ),
        'return_value':
        fields.function(
            _line_total_amount,
            method=True,
            string='Total return',
            type='float',
            help="Quantity returned * Unit sold price",
        ),
        'prodlot_id':
        fields.many2one('stock.production.lot',
                        'Serial/Lot n°',
                        help="The serial/lot of the returned product"),
        'applicable_guarantee':
        fields.selection(
            [('us', 'Company'), ('supplier', 'Supplier'),
             ('brand', 'Brand manufacturer')], 'Warranty type'
        ),  # TODO: Replace with function field. type supplier might generate an auto draft forward to the supplier
        'guarantee_limit':
        fields.date(
            'Warranty limit',
            help=
            "The warranty limit is computed as: invoice date + warranty defined on selected product.",
            readonly=True),
        'warning':
        fields.char('Warranty',
                    size=64,
                    readonly=True,
                    help="If warranty has expired"),
        'warranty_type':
        fields.char('Warranty type',
                    size=64,
                    readonly=True,
                    help="from product form"),
        "warranty_return_partner":
        fields.many2one(
            'res.partner',
            'Warranty return',
            help="Where the customer has to send back the product(s)"),
        'claim_id':
        fields.many2one('crm.claim',
                        'Related claim',
                        help="To link to the case.claim object"),
        'state':
        fields.selection([('draft', 'Draft'), ('refused', 'Refused'),
                          ('confirmed', 'Confirmed, waiting for product'),
                          ('in_to_control', 'Received, to control'),
                          ('in_to_treate', 'Controlled, to treate'),
                          ('treated', 'Treated')], 'State'),
        'substate_id':
        fields.many2one(
            'substate.substate',
            'Sub state',
            help=
            "Select a sub state to precise the standard state. Example 1: state = refused; substate could be warranty over, not in warranty, no problem,... . Example 2: state = to treate; substate could be to refund, to exchange, to repair,..."
        ),
        'last_state_change':
        fields.date('Last change',
                    help="To set the last state / substate change"),
        'invoice_line_id':
        fields.many2one(
            'account.invoice.line',
            'Invoice Line',
            help='The invoice line related to the returned product'),
        'refund_line_id':
        fields.many2one(
            'account.invoice.line',
            'Refund Line',
            help='The refund line related to the returned product'),
        'move_in_id':
        fields.many2one('stock.move',
                        'Move Line from picking in',
                        help='The move line related to the returned product'),
        'move_out_id':
        fields.many2one('stock.move',
                        'Move Line from picking out',
                        help='The move line related to the returned product'),
    }

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

    # Method to calculate warranty limit
    def set_warranty_limit(self, cr, uid, ids, claim_line, context=None):
        date_invoice = claim_line.invoice_line_id.invoice_id.date_invoice
        if date_invoice:
            warning = "Valid"
            if claim_line.claim_id.claim_type == 'supplier':
                if claim_line.prodlot_id:
                    limit = (
                        datetime.strptime(date_invoice,
                                          DEFAULT_SERVER_DATE_FORMAT) +
                        relativedelta(
                            months=int(claim_line.product_id.seller_ids[0].
                                       warranty_duration))
                    ).strftime(
                        DEFAULT_SERVER_DATE_FORMAT)  # TODO: To be implemented
                else:
                    limit = (datetime.strptime(date_invoice,
                                               DEFAULT_SERVER_DATE_FORMAT) +
                             relativedelta(
                                 months=int(claim_line.product_id.
                                            seller_ids[0].warranty_duration))
                             ).strftime(DEFAULT_SERVER_DATE_FORMAT)
            else:
                limit = (
                    datetime.strptime(date_invoice, DEFAULT_SERVER_DATE_FORMAT)
                    + relativedelta(months=int(claim_line.product_id.warranty))
                ).strftime(DEFAULT_SERVER_DATE_FORMAT)
            if limit < claim_line.claim_id.date:
                warning = 'Expired'
            self.write(cr, uid, ids, {
                'guarantee_limit': limit,
                'warning': warning,
            })
        else:
            raise osv.except_osv(
                _('Error !'),
                _('Cannot find any date for invoice ! Must be a validated invoice !'
                  ))
        return True

    # Method to calculate warranty return address
    def set_warranty_return_address(self,
                                    cr,
                                    uid,
                                    ids,
                                    claim_line,
                                    context=None):
        return_address = None
        warranty_type = 'company'
        seller = claim_line.product_id.seller_info_id
        if seller:
            return_partner = seller.warranty_return_partner
            if return_partner:
                warranty_type = return_partner
            else:
                warranty_type = 'company'
            return_address = seller.warranty_return_address.id
#                if return_partner == 'company':
#                    return_address = self._get_partner_address(cr, uid, ids, context,claim_line.claim_id.company_id.partner_id)[0]
#                elif return_partner == 'supplier':
#                    return_address = self._get_partner_address(cr, uid, ids, context,claim_line.product_id.seller_ids[0].name)[0]
#                    warranty_type = 'supplier'
#                elif return_partner == 'brand':
#                    return_address = self._get_partner_address(cr, uid, ids, context, claim_line.product_id.product_brand_id.partner_id)[0]
#                    warranty_type = 'brand'
#                else :
#                    warranty_type = 'other'
#                    # TO BE IMPLEMENTED if something to do...
#            else :
#                warranty_type = 'company'
#                return_address = self._get_default_company_address(cr, uid, claim_line.claim_id.company_id, context=context)
#TODO fix me use default address
#                self.write(cr,uid,ids,{'warranty_return_partner':1,'warranty_type': 'company'})
#                return True

#raise osv.except_osv(_('Error !'), _('Cannot find any warranty return partner for this product !'))
        else:
            warranty_type = 'company'
            if claim_line.claim_id.company_id.crm_return_address_id:
                return_address = [
                    claim_line.claim_id.company_id.crm_return_address_id.id
                ]
            else:
                return_address = [
                    claim_line.claim_id.company_id.partner_id.address[0].id
                ]
#            return_address = self._get_default_company_address(cr, uid, claim_line.claim_id.company_id, context=context)
#TODO fix me use default address
#            self.write(cr,uid,ids,{'warranty_return_partner':1,'warranty_type': 'company'})
#            return True
#raise osv.except_osv(_('Error !'), _('Cannot find any supplier for this product !'))
        self.write(
            cr, uid, ids, {
                'warranty_return_partner': return_address,
                'warranty_type': warranty_type
            })
        return True

    # Method to calculate warranty limit and validity
    def set_warranty(self, cr, uid, ids, context=None):
        for claim_line in self.browse(cr, uid, ids, context=context):
            if claim_line.product_id and claim_line.invoice_line_id:
                self.set_warranty_limit(cr, uid, ids, claim_line, context)
                self.set_warranty_return_address(cr, uid, ids, claim_line,
                                                 context)
            else:
                raise osv.except_osv(_('Error !'),
                                     _('PLEASE SET PRODUCT & INVOICE!'))
        return True
Example #48
0
 "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",
Example #49
0
class hr_expense_line(osv.osv):
    _name = "hr.expense.line"
    _description = "Expense Line"

    def _amount(self, cr, uid, ids, field_name, arg, context=None):
        if not ids:
            return {}
        cr.execute(
            "SELECT l.id,COALESCE(SUM(l.unit_amount*l.unit_quantity),0) AS amount FROM hr_expense_line l WHERE id IN %s GROUP BY l.id ",
            (tuple(ids), ))
        res = dict(cr.fetchall())
        return res

    def _get_uom_id(self, cr, uid, context=None):
        result = self.pool.get('ir.model.data').get_object_reference(
            cr, uid, 'product', 'product_uom_unit')
        return result and result[1] or False

    _columns = {
        'name':
        fields.char('Expense Note', required=True),
        'date_value':
        fields.date('Date', required=True),
        'expense_id':
        fields.many2one('hr.expense.expense',
                        'Expense',
                        ondelete='cascade',
                        select=True),
        'total_amount':
        fields.function(_amount,
                        string='Total',
                        digits_compute=dp.get_precision('Account')),
        'unit_amount':
        fields.float('Unit Price',
                     digits_compute=dp.get_precision('Product Price')),
        'unit_quantity':
        fields.float(
            'Quantities',
            digits_compute=dp.get_precision('Product Unit of Measure')),
        'product_id':
        fields.many2one('product.product',
                        'Product',
                        domain=[('hr_expense_ok', '=', True)]),
        'uom_id':
        fields.many2one('product.uom', 'Unit of Measure', required=True),
        'description':
        fields.text('Description'),
        'analytic_account':
        fields.many2one('account.analytic.account', 'Analytic account'),
        'ref':
        fields.char('Reference'),
        'sequence':
        fields.integer(
            'Sequence',
            select=True,
            help=
            "Gives the sequence order when displaying a list of expense lines."
        ),
    }
    _defaults = {
        'unit_quantity': 1,
        'date_value': lambda *a: time.strftime('%Y-%m-%d'),
        'uom_id': _get_uom_id,
    }
    _order = "sequence, date_value desc"

    def onchange_product_id(self, cr, uid, ids, product_id, context=None):
        res = {}
        if product_id:
            product = self.pool.get('product.product').browse(cr,
                                                              uid,
                                                              product_id,
                                                              context=context)
            res['name'] = product.name
            amount_unit = product.price_get('standard_price')[product.id]
            res['unit_amount'] = amount_unit
            res['uom_id'] = product.uom_id.id
        return {'value': res}

    def onchange_uom(self, cr, uid, ids, product_id, uom_id, context=None):
        res = {'value': {}}
        if not uom_id or not product_id:
            return res
        product = self.pool.get('product.product').browse(cr,
                                                          uid,
                                                          product_id,
                                                          context=context)
        uom = self.pool.get('product.uom').browse(cr,
                                                  uid,
                                                  uom_id,
                                                  context=context)
        if uom.category_id.id != product.uom_id.category_id.id:
            res['warning'] = {
                'title':
                _('Warning'),
                'message':
                _('Selected Unit of Measure does not belong to the same category as the product Unit of Measure'
                  )
            }
            res['value'].update({'uom_id': product.uom_id.id})
        return res
Example #50
0
class account_caja_chica(osv.osv):

    _order = "date desc, id desc"
    _name = "account.caja.chica"
    _description = "Caja Chica"

    #    _inherit = ['mail.thread']

    def _get_default_company(self, cr, uid, context=None):
        company_id = self.pool.get('res.users')._get_company(cr,
                                                             uid,
                                                             context=context)
        if not company_id:
            raise osv.except_osv(
                _('Error!'),
                _('There is no default company for the current user!'))
        return company_id

    _columns = {
        'name':
        fields.char(
            'Referencia',
            states={'draft': [('readonly', False)]},
            readonly=True,  # readonly for account_cash_statement
            copy=False,
            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'),
        'date':
        fields.date('Fecha Caja',
                    required=True,
                    states={'confirm': [('readonly', True)]},
                    select=True,
                    copy=False),
        'date_cierre':
        fields.date('Fecha Cierre',
                    states={'draft': [('readonly', True)]},
                    select=True,
                    copy=False),
        'user_id':
        fields.many2one('res.users',
                        'Responsable',
                        states={
                            'draft': [('readonly', False)],
                            'open': [('readonly', False)]
                        },
                        select=True,
                        track_visibility='onchange'),
        'saldo_ini':
        fields.float('Saldo Inicial',
                     digits_compute=dp.get_precision('Account'),
                     states={'confirm': [('readonly', True)]}),
        'saldo_pend':
        fields.float('Saldo Pendiente',
                     digits_compute=dp.get_precision('Account'),
                     states={'confirm': [('readonly', True)]}),
        'valor_bruto':
        fields.float('Valor Bruto',
                     digits_compute=dp.get_precision('Account'),
                     states={'confirm': [('readonly', True)]}),
        'valor_neto':
        fields.float('Neto Pagar',
                     digits_compute=dp.get_precision('Account'),
                     states={'confirm': [('readonly', True)]}),
        'valor_iva':
        fields.float('Valor Iva',
                     digits_compute=dp.get_precision('Account'),
                     states={'confirm': [('readonly', True)]}),
        'valor_bruto_f':
        fields.float('Valor Bruto F',
                     digits_compute=dp.get_precision('Account'),
                     states={'confirm': [('readonly', True)]}),
        'valor_neto_f':
        fields.float('Neto Pagar F',
                     digits_compute=dp.get_precision('Account'),
                     states={'confirm': [('readonly', True)]}),
        'valor_iva_f':
        fields.float('Valor Iva F',
                     digits_compute=dp.get_precision('Account'),
                     states={'confirm': [('readonly', True)]}),
        'company_id':
        fields.related('company_id',
                       type='many2one',
                       relation='res.company',
                       string='Compañia',
                       store=True,
                       readonly=True),
        #'company_id': fields.many2one('res.company', 'Company'),
        'line_ids':
        fields.one2many('account.caja.chica.line',
                        'caja_chica_id',
                        'Caja chica lines',
                        states={'confirm': [('readonly', True)]},
                        copy=True),
        'state':
        fields.selection(
            [
                ('draft', 'New'),
                ('open', 'Open'),  # CSV:2016-04-21 used by cash statements
                ('pending', 'Pendiente'),  # CSV:2016-04-21 used by pay partial
                ('confirm', 'Closed')
            ],
            'Status',
            required=True,
            readonly="1",
            copy=False,
            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.'
        ),
    }

    _defaults = {
        'name':
        'Caja Chica/',
        'date':
        fields.date.context_today,
        'state':
        'draft',
        #'company_id': _get_default_company,
        'company_id':
        lambda self, cr, uid, c: self.pool.get('res.company').
        _company_default_get(cr, uid, 'account.caja.chica', context=c),
        'user_id':
        lambda obj, cr, uid, context: uid,
    }

    def cerrar_caja(self, cr, uid, ids, context=None):
        lis_rec = []
        band = 0
        obj_caja = self.browse(cr, uid, ids)[0]
        self.write(cr, uid, ids, {'state': 'pending'})
        #Creo un registro de caja nuevo con el saldo pendiente como inicial para la nueva caja
        data = {
            'name': obj_caja.name,
            'user_id': obj_caja.user_id.id,
            'date': time.strftime('%Y-%m-%d %H:%M:%S'),
            'company_id': obj_caja.company_id.id,
            'saldo_ini': obj_caja.saldo_pend,
            'state': 'draft',
        }
        self.create(cr, uid, data, context)
        return True

    def validar_caja(self, cr, uid, ids, context=None):
        band = 0
        lis_rec = []
        invoice_id = False
        obj_caja = self.browse(cr, uid, ids)[0]
        self.write(cr, uid, ids, {
            'state': 'confirm',
            'date_cierre': time.strftime('%Y-%m-%d %H:%M:%S')
        })
        inv_obj = self.pool.get('account.invoice')
        acc_jour_obj = self.pool.get('account.journal')
        inv_line_obj = self.pool.get('account.invoice.line')
        cchica_lin_obj = self.pool.get('account.caja.chica.line')
        cchica_line_ids = cchica_lin_obj.search(
            cr,
            uid, [('caja_chica_id', '=', obj_caja.id)],
            order='id, number_fact')
        stat_conc_line_obj = cchica_lin_obj.browse(cr,
                                                   uid,
                                                   cchica_line_ids,
                                                   context=context)
        # JJM 2018-02-15 utilizo el superuser_id por que se necesita validar cajas chicas de otras companias
        # evito regla de registro para account_journal sobre company_id
        journal_id = acc_jour_obj.search(
            cr, SUPERUSER_ID, [('code', '=', 'DCC'),
                               ('company_id', '=', obj_caja.company_id.id)])
        if not journal_id:
            raise osv.except_osv(
                _('Advertencia!'),
                _('Primero debe crear un diario de caja chica para esta compania con codigo DCC!'
                  ))
        journal_obj = acc_jour_obj.browse(cr, uid, journal_id, context=context)
        for ji in journal_obj:
            id_journal = ji.id
        num_comp = ''
        for det_cc in stat_conc_line_obj:
            #CONDICION SI ES COMPROBANTE TIPO FACTURA
            #print "LINEAS ID", det_cc.id
            #print "LINEAS", det_cc.product_id.name
            # JJM 2017-01-28 comento siguiente linea, ahora tomo cuenta desde la compañia
            #account_id = self.pool.get('multi.account.partner.rel').search(cr, uid, [('partner_id', '=', det_cc.partner_id.id),
            #                                                                         ('type', '=', 'payable'),
            #                                                                         ('company_id', '=', det_cc.company_id.id)])
            if not det_cc.partner_id:
                raise osv.except_orm(
                    'Advertencia!',
                    'Debe ingresar un proveedor para la linea de %s' %
                    (det_cc.name))
            if len(det_cc.company_id.payable_ids) == 0:
                raise osv.except_orm(
                    'Advertencia!',
                    'La compania %s no tiene configurada la cuenta a pagar Proveedores'
                    % det_cc.company_id.name)
            # JJM ahora tomo la cuenta desde la compañia en lugar del multi.account
            account_id = det_cc.company_id.payable_ids[0].id
            #account_id = self.pool.get('multi.account.partner.rel').browse(cr, uid, account_id[0]).property_account.id
            if not det_cc.sudo(
                    det_cc.user_id).product_id.property_account_expense:
                raise osv.except_orm(
                    'Advertencia!',
                    'No tiene configurada la cuenta de gastos para el producto %s'
                    % (det_cc.product_id.name))
            if det_cc.cantidad <= 0:
                raise osv.except_orm(
                    'Advertencia!',
                    'la cantidad del producto %s no puede ser cero' %
                    (det_cc.product_id.name))

            if det_cc.tipo_comp == 'factura':
                #CREO REGISTRO NUEVO SOLO SI ES COMPROBANTE DIFERENTE
                if det_cc.tipo_comp == 'factura' and det_cc.number_fact != num_comp:
                    num_comp = det_cc.number_fact
                    #Creo cabecera Factura
                    vals_invoice = {
                        'name':
                        'CCHICA' + '-' + time.strftime('%Y-%m-%d %H:%M:%S'),
                        'journal_id':
                        id_journal,
                        'number_seq':
                        det_cc.number_fact,
                        'account_id':
                        account_id,
                        'partner_id':
                        det_cc.partner_id.id,
                        'company_id':
                        det_cc.company_id.id,
                        'reference':
                        det_cc.name,
                        'type':
                        'in_invoice',
                        'document_type':
                        1,
                        'is_cchica':
                        True,
                        'is_asum':
                        True,
                        'is_inv_elect':
                        False,
                        'date_invoice':
                        time.strftime('%Y-%m-%d %H:%M:%S'),
                        'origin':
                        'CCHICA' + '-' + time.strftime('%Y-%m-%d %H:%M:%S'),
                        'state':
                        'draft'
                    }
                    print "DICCIO FACT", vals_invoice
                    invoice_id = inv_obj.create(cr,
                                                uid,
                                                vals_invoice,
                                                context=context)
                    #Creo detalle Factura
                    if invoice_id:
                        vals_det_invoice = {
                            'name':
                            'CCHICA' + '-' +
                            time.strftime('%Y-%m-%d %H:%M:%S'),
                            'invoice_id':
                            invoice_id,
                            'company_id':
                            det_cc.company_id.id,
                            'partner_id':
                            det_cc.partner_id.id,
                            'product_id':
                            det_cc.product_id.id,
                            'quantity':
                            det_cc.cantidad,
                            'account_id':
                            det_cc.sudo(det_cc.user_id).product_id.
                            property_account_expense.id,
                            'price_unit':
                            round(det_cc.amount_neto / det_cc.cantidad, 2),
                            'price_subtotal':
                            round(det_cc.amount_neto / det_cc.cantidad, 2),
                            'origin':
                            'CCHICA' + '-' +
                            time.strftime('%Y-%m-%d %H:%M:%S'),
                        }
                        invoice_line_id = inv_line_obj.create(
                            cr, uid, vals_det_invoice)
                # CREO UNA LINEA MAS NADA MAS PORQUE ES DE LA MISMA FACTURA
                elif det_cc.tipo_comp == 'factura' and det_cc.number_fact == num_comp:
                    num_comp = det_cc.number_fact
                    #Creo detalle Factura
                    if invoice_id:
                        vals_det_invoice = {
                            'name':
                            'CCHICA' + '-' +
                            time.strftime('%Y-%m-%d %H:%M:%S'),
                            'invoice_id':
                            invoice_id,
                            'company_id':
                            det_cc.company_id.id,
                            'partner_id':
                            det_cc.partner_id.id,
                            'product_id':
                            det_cc.product_id.id,
                            'quantity':
                            det_cc.cantidad,
                            'account_id':
                            det_cc.sudo(det_cc.user_id).product_id.
                            property_account_expense.id,
                            'price_unit':
                            round(det_cc.amount_neto / det_cc.cantidad, 2),
                            'price_subtotal':
                            round(det_cc.amount_neto / det_cc.cantidad, 2),
                            'origin':
                            'CCHICA' + '-' +
                            time.strftime('%Y-%m-%d %H:%M:%S'),
                        }
                        invoice_line_id = inv_line_obj.create(
                            cr, uid, vals_det_invoice)
            #CONDICION SI ES COMPROBANTE TIPO NOTA VENTA
            elif det_cc.tipo_comp == 'nventa':
                #CREO REGISTRO NUEVO SOLO SI ES COMPROBANTE DIFERENTE
                if det_cc.tipo_comp == 'nventa' and det_cc.number_fact != num_comp:
                    num_comp = det_cc.number_fact
                    #Creo cabecera COMPROBANTE TIPO NOTA VENTA
                    vals_invoice = {
                        'name':
                        'CCHICA' + '-' + time.strftime('%Y-%m-%d %H:%M:%S'),
                        'journal_id':
                        id_journal,
                        'number_seq':
                        det_cc.number_fact,
                        'account_id':
                        account_id,
                        'partner_id':
                        det_cc.partner_id.id,
                        'company_id':
                        det_cc.company_id.id,
                        'reference':
                        det_cc.name,
                        'type':
                        'in_invoice',
                        'document_type':
                        2,
                        'is_cchica':
                        True,
                        'is_asum':
                        True,
                        'is_inv_elect':
                        False,
                        'date_invoice':
                        time.strftime('%Y-%m-%d %H:%M:%S'),
                        'origin':
                        'CCHICA' + '-' + time.strftime('%Y-%m-%d %H:%M:%S'),
                        'state':
                        'draft'
                    }
                    invoice_id = inv_obj.create(cr,
                                                uid,
                                                vals_invoice,
                                                context=context)
                    #Creo detalle COMPROBANTE TIPO NOTA VENTA
                    if invoice_id:
                        vals_det_invoice = {
                            'name':
                            'CCHICA' + '-' +
                            time.strftime('%Y-%m-%d %H:%M:%S'),
                            'invoice_id':
                            invoice_id,
                            'company_id':
                            det_cc.company_id.id,
                            'partner_id':
                            det_cc.partner_id.id,
                            'product_id':
                            det_cc.product_id.id,
                            'quantity':
                            det_cc.cantidad,
                            'account_id':
                            det_cc.sudo(det_cc.user_id).product_id.
                            property_account_expense.id,
                            'price_unit':
                            round(det_cc.amount_neto / det_cc.cantidad, 2),
                            'price_subtotal':
                            round(det_cc.amount_neto / det_cc.cantidad, 2),
                            'origin':
                            'CCHICA' + '-' +
                            time.strftime('%Y-%m-%d %H:%M:%S'),
                        }
                        invoice_line_id = inv_line_obj.create(
                            cr, uid, vals_det_invoice)
                # CREO UNA LINEA MAS NADA MAS PORQUE ES DE LA MISMO COMPROBANTE TIPO NOTA VENTA
                elif det_cc.tipo_comp == 'nventa' and det_cc.number_fact == num_comp:
                    num_comp = det_cc.number_fact
                    #Creo detalle COMPROBANTE TIPO NOTA VENTA
                    if invoice_id:
                        vals_det_invoice = {
                            'name':
                            'CCHICA' + '-' +
                            time.strftime('%Y-%m-%d %H:%M:%S'),
                            'invoice_id':
                            invoice_id,
                            'company_id':
                            det_cc.company_id.id,
                            'partner_id':
                            det_cc.partner_id.id,
                            'product_id':
                            det_cc.product_id.id,
                            'quantity':
                            det_cc.cantidad,
                            'account_id':
                            det_cc.sudo(det_cc.user_id).product_id.
                            property_account_expense.id,
                            'price_unit':
                            round(det_cc.amount_neto / det_cc.cantidad, 2),
                            'price_subtotal':
                            round(det_cc.amount_neto / det_cc.cantidad, 2),
                            'origin':
                            'CCHICA' + '-' +
                            time.strftime('%Y-%m-%d %H:%M:%S'),
                        }
                        invoice_line_id = inv_line_obj.create(
                            cr, uid, vals_det_invoice)
            else:
                vals_recibo = {
                    'name':
                    'CCHICA' + '-' + time.strftime('%Y-%m-%d %H:%M:%S'),
                    'journal_id':
                    id_journal,
                    'account_id':
                    account_id,
                    'partner_id':
                    det_cc.partner_id.id,
                    'company_id':
                    det_cc.company_id.id,
                    'reference':
                    det_cc.name,
                    'date_invoice':
                    time.strftime('%Y-%m-%d %H:%M:%S'),
                    'origin':
                    'CCHICA' + '-' + time.strftime('%Y-%m-%d %H:%M:%S'),
                    'product_id':
                    det_cc.product_id.id,
                    'quantity':
                    det_cc.cantidad,
                    'account_line_id':
                    det_cc.sudo(
                        det_cc.user_id).product_id.property_account_expense.id,
                    'price_unit':
                    round(det_cc.amount_neto / det_cc.cantidad, 2),
                    'price_subtotal':
                    round(det_cc.amount_neto / det_cc.cantidad, 2)
                }
                lis_rec.append(vals_recibo)
                band = 1
        if band == 1:
            band1 = 0
            for inv_rec in lis_rec:
                #Creo cabecera Factura
                if band1 == 0:
                    vals_invoice = {
                        'name': inv_rec.get('name'),
                        #'journal_id': det_cc.journal_id.id,
                        'account_id': inv_rec.get('account_id'),
                        'partner_id': inv_rec.get('partner_id'),
                        'company_id': inv_rec.get('company_id'),
                        'reference': inv_rec.get('reference'),
                        'type': 'in_invoice',
                        'document_type': 3,
                        'is_cchica': True,
                        'is_asum': True,
                        'is_inv_elect': False,
                        'date_invoice': inv_rec.get('date_invoice'),
                        'origin': inv_rec.get('origin'),
                        'state': 'draft'
                    }
                    invoice_idr = inv_obj.create(cr,
                                                 uid,
                                                 vals_invoice,
                                                 context=context)
                    band1 = 1
                #Creo detalle Factura
                if invoice_idr:
                    vals_det_invoice = {
                        'name': inv_rec.get('name'),
                        'invoice_id': invoice_idr,
                        'company_id': inv_rec.get('company_id'),
                        'partner_id': inv_rec.get('partner_id'),
                        'product_id': inv_rec.get('product_id'),
                        'quantity': inv_rec.get('quantity'),
                        'account_id': inv_rec.get('account_line_id'),
                        'price_unit': inv_rec.get('price_unit'),
                        'price_subtotal': inv_rec.get('price_subtotal'),
                        'origin': inv_rec.get('origin'),
                    }
                    invoice_line_id = inv_line_obj.create(
                        cr, uid, vals_det_invoice)

        return True

    def new_ingreso(self, cr, uid, ids, context=None):
        lis_rec = []
        band = 0
        obj_caja = self.browse(cr, uid, ids)[0]
        stock_ware = self.pool.get('stock.picking.type')
        picking_obj = self.pool.get('stock.picking')
        move_obj = self.pool.get('stock.move')
        cchica_lin_obj = self.pool.get('account.caja.chica.line')
        cchica_line_ids = cchica_lin_obj.search(
            cr, uid, [('caja_chica_id', '=', obj_caja.id)])
        stat_conc_line_obj = cchica_lin_obj.browse(cr,
                                                   uid,
                                                   cchica_line_ids,
                                                   context=context)
        band = 0
        for det_cc in stat_conc_line_obj:
            #CONDICION SI ES INVENTARIO PARA PROCESAR
            print "IS INVENT", det_cc.is_inven
            print "STATE", det_cc.state
            if det_cc.is_inven and det_cc.state == 'open':
                if det_cc.product_id.type in ('product', 'consu'):
                    print "PROCESO INVENTARIO Y CONFIRMO LINEA MARCADA", det_cc.id
                    vals_lcchica = {'state': 'confirm'}
                    cchica_lin_obj.write(cr, uid, det_cc.id, vals_lcchica)
                    pic_type_id = stock_ware.search(
                        cr, uid, [('code', '=', 'incoming'),
                                  ('warehouse_id.company_id', '=',
                                   det_cc.user_id.company_id.id),
                                  ('name', '=', 'Recepciones')])
                    print "ID PIC TYPE", pic_type_id
                    if not pic_type_id:
                        raise osv.except_osv(
                            _('Advertencia!'),
                            _('Primero debe crear un tipo de albarran recepción para la compania de la operación!'
                              ))
                    pic_type_obj = stock_ware.browse(cr,
                                                     uid,
                                                     pic_type_id,
                                                     context=context)
                    for sw in pic_type_obj:
                        id_pt = sw.id
                        wareh_id = sw.warehouse_id.id
                        ub_origen = sw.default_location_src_id.id
                        ub_destino = sw.default_location_dest_id.id
                    if band == 0:
                        picking_vals = {
                            'picking_type_id':
                            id_pt,
                            'partner_id':
                            det_cc.partner_id.id,
                            'date':
                            time.strftime('%Y-%m-%d %H:%M:%S'),
                            'origin':
                            'CCHICA' + '-' + time.strftime('%Y-%m-%d %H:%M:%S')
                            or ''
                        }
                        picking_id = picking_obj.create(cr,
                                                        uid,
                                                        picking_vals,
                                                        context=context)
                        band = 1
                    if picking_id:
                        vals_stock_move = {
                            'name':
                            'CCHICA' + '-' + time.strftime('%Y-%m-%d %H:%M:%S')
                            or '',
                            'product_id':
                            det_cc.product_id.id,
                            'product_uom':
                            det_cc.product_id.uom_id.id,
                            'product_uos':
                            det_cc.product_id.uos_id.id,
                            'date':
                            time.strftime('%Y-%m-%d %H:%M:%S'),
                            'date_expected':
                            time.strftime('%Y-%m-%d %H:%M:%S'),
                            'location_id':
                            ub_origen,
                            'location_dest_id':
                            ub_destino,
                            'picking_id':
                            picking_id,
                            'partner_id':
                            det_cc.partner_id.id,
                            'move_dest_id':
                            False,
                            'state':
                            'draft',
                            #'purchase_line_id': order_line.id,
                            'company_id':
                            det_cc.user_id.company_id.id,
                            'product_uom_qty':
                            det_cc.cantidad,
                            'price_unit':
                            round(det_cc.amount_neto / det_cc.cantidad, 2),
                            'picking_type_id':
                            id_pt,
                            #'group_id': group_id,
                            'procurement_id':
                            False,
                            'origin':
                            'CCHICA' + '-' +
                            time.strftime('%Y-%m-%d %H:%M:%S'),
                            #'route_ids': order.picking_type_id.warehouse_id and [(6, 0, [x.id for x in order.picking_type_id.warehouse_id.route_ids])] or [],
                            'warehouse_id':
                            wareh_id,
                            'invoice_state':
                            '2binvoiced',
                        }
                        stock_move_id = move_obj.create(
                            cr, uid, vals_stock_move)
                else:
                    raise osv.except_osv(
                        _('Advertencia!'),
                        _('No puede crear albarran de un producto que no es de stock!'
                          ))
            # else:
            #     raise osv.except_osv(_('Advertencia!'), _('Ya no hay mas lineas marcadas para procesar albarranes de ingreso!'))
        return True

    def button_dummy(self, cr, uid, ids, context=None):
        print "IDS***", ids
        conci_obj = self.pool.get('account.caja.chica')
        conci_lin_obj = self.pool.get('account.caja.chica.line')
        stat_conc_line_ids = conci_lin_obj.search(
            cr, uid, [('caja_chica_id', '=', ids)])
        stat_conc_line_obj = conci_lin_obj.browse(cr,
                                                  uid,
                                                  stat_conc_line_ids,
                                                  context=context)
        valor_bruto = 0.00
        valor_neto = 0.00
        valor_iva = 0.00
        valor_brutof = 0.00
        valor_netof = 0.00
        valor_ivaf = 0.00
        for cc in self.browse(cr, uid, ids, context=context):
            sal_ini = cc.saldo_ini
        print "SAL INI", sal_ini
        for st_lin in stat_conc_line_obj:
            valor_bruto += round(st_lin.amount, 2)
            valor_neto += round(st_lin.amount_neto, 2)
            valor_iva += round(st_lin.amount_iva_retenido, 2)
            if st_lin.iva_fact:
                valor_brutof += round(st_lin.amount, 2)
                valor_netof += round(st_lin.amount_neto, 2)
                valor_ivaf += round(st_lin.amount_iva_retenido, 2)
        vals_stat = {
            'valor_bruto': valor_bruto,
            'saldo_pend': sal_ini - valor_bruto,
            'valor_neto': valor_neto,
            'valor_iva': valor_iva,
            'valor_bruto_f': valor_brutof,
            'valor_neto_f': valor_netof,
            'valor_iva_f': valor_ivaf
        }
        conci_obj.write(cr, uid, ids, vals_stat)
        return self.write(cr, uid, ids, {'state': 'open'}, context=context)

    def button_cancel(self, cr, uid, ids, context=None):
        bnk_st_line_ids = []
        #CSV 13-06-2017 Comento para cancelar caja chica no manejo asientos
        # for st in self.browse(cr, uid, ids, context=context):
        #     bnk_st_line_ids += [line.id for line in st.line_ids]
        # self.pool.get('account.caja.chica.line').cancel(cr, uid, bnk_st_line_ids, context=context)
        return self.write(cr, uid, ids, {'state': 'open'}, context=context)

    def abrir_caja(self, cr, uid, ids, context=None):
        print "abrir_caja: ", ids
        self.write(cr, uid, ids, {
            'state': 'open',
            'date': time.strftime('%Y-%m-%d %H:%M:%S')
        })
        return True
Example #51
0
class account_caja_chica_line(osv.osv):
    def cancel(self, cr, uid, ids, context=None):
        account_move_obj = self.pool.get('account.move')
        move_ids = []
        for line in self.browse(cr, uid, ids, context=context):
            if line.journal_entry_id:
                move_ids.append(line.journal_entry_id.id)
                for aml in line.journal_entry_id.line_id:
                    if aml.reconcile_id:
                        move_lines = [l.id for l in aml.reconcile_id.line_id]
                        move_lines.remove(aml.id)
                        self.pool.get('account.move.reconcile').unlink(
                            cr, uid, [aml.reconcile_id.id], context=context)
                        if len(move_lines) >= 2:
                            self.pool.get(
                                'account.move.line').reconcile_partial(
                                    cr,
                                    uid,
                                    move_lines,
                                    'auto',
                                    context=context)
        if move_ids:
            account_move_obj.button_cancel(cr, uid, move_ids, context=context)
            account_move_obj.unlink(cr, uid, move_ids, context)

    _order = "caja_chica_id desc"
    _name = "account.caja.chica.line"
    _description = "Caja Chica Detalle"
    #    _inherit = ['ir.needaction_mixin']
    _columns = {
        'name':
        fields.char('Concepto', required=True),
        'date':
        fields.date('Fecha', required=True),
        'partner_id':
        fields.many2one('res.partner', 'Proveedor'),
        'product_id':
        fields.many2one('product.product', 'Producto'),
        'cantidad':
        fields.float('Cantidad',
                     select=True,
                     help="Cantidad requerida.",
                     digits_compute=dp.get_precision('Account')),
        'amount':
        fields.float('Total', digits_compute=dp.get_precision('Account')),
        'caja_chica_id':
        fields.many2one('account.caja.chica',
                        'Caja Chica',
                        select=True,
                        required=True,
                        ondelete='restrict'),
        'amount_iva_retenido':
        fields.float(
            'Iva',
            help=
            "The amount expressed in an optional other currency if it is a multi-currency entry.",
            digits_compute=dp.get_precision('Account')),
        'amount_neto':
        fields.float(
            'Subtotal',
            help=
            "The amount expressed in an optional other currency if it is a multi-currency entry.",
            digits_compute=dp.get_precision('Account')),
        'is_inven':
        fields.boolean(
            'Inventario',
            help="Marcar si es un registro que necesitamos afecte inventarios"
        ),
        'is_iva':
        fields.boolean('IVA', help="Marcar si es un registro que aplica iva"),
        'iva_fact':
        fields.boolean(
            'I.F',
            help=
            "Marcar si quiere verificar el valor total del iva de la factura saldra en la parte inferior"
        ),
        'user_id':
        fields.many2one('res.users', 'Responsable', required=False),
        'company_id':
        fields.related('caja_chica_id',
                       'company_id',
                       type='many2one',
                       relation='res.company',
                       string='Company',
                       store=True,
                       readonly=True),
        #'partner_name': fields.char('Proveedor Nombre', help="Este campo es usado en el caso que no exista el proveedor requerido para que contabilidad lo cree"),
        #'note': fields.text('Notes'),
        'sequence':
        fields.integer(
            'Sequence',
            select=True,
            help=
            "Gives the sequence order when displaying a list of caja chica."),
        'number_fact':
        fields.char('Factura', size=9, required=True),
        'tipo_comp':
        fields.selection(
            [('factura', 'Factura'), ('recibo', 'Recibo'),
             ('nventa', 'N. Venta')],
            'Documento',
            required=True,
            copy=False,
            help='Seleccione el tipo de documento que esta registrando.'),
        'state':
        fields.selection(
            [
                ('open', 'Open'),  # CSV:2016-04-21 used by cash statements
                ('confirm', 'Closed')
            ],
            'Status',
            required=True,
            readonly="1",
            copy=False,
            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.'
        ),
        'por_iva':
        fields.selection([('10', '10%'), ('12', '12%'), ('14', '14%')],
                         '%IVA',
                         required=True,
                         copy=False,
                         help='Seleccione el % de iva de la factura.'),
    }
    _defaults = {
        #'name': lambda self,cr,uid,context={}: self.pool.get('ir.sequence').get(cr, uid, 'account.caja.chica.line'),
        'date': lambda self, cr, uid, context={}: context.get(
            'date', fields.date.context_today(self, cr, uid, context=context)),
        'user_id': lambda obj, cr, uid, context: uid,
        'state': 'open',
        'por_iva': '12',
    }

    def onchange_is_factura(self, cr, uid, ids, tipo_comp, context=None):
        result = {}
        print "TIPO Comp", tipo_comp

        if tipo_comp == 'factura':
            result = {'value': {'is_iva': True}}
        else:
            result = {'value': {'is_iva': False}}
        return result

    def onchange_valor_iva(self,
                           cr,
                           uid,
                           ids,
                           tipo_comp,
                           is_iva,
                           amount_neto,
                           por_iva,
                           context=None):
        result = {}
        print "TIPO COMP", tipo_comp
        print "IS IVA", is_iva
        print "SUBTOTAL", amount_neto
        iva = int(por_iva)

        if tipo_comp == 'factura' and is_iva:
            result = {
                'value': {
                    'amount_iva_retenido': round((amount_neto * iva) / 100, 2),
                    'amount': round(amount_neto + ((amount_neto * iva) / 100),
                                    2)
                }
            }
        elif tipo_comp == 'factura' and not is_iva:
            result = {
                'value': {
                    'amount_iva_retenido': 0.00,
                    'amount': round(amount_neto, 2)
                }
            }
        else:
            result = {
                'value': {
                    'amount_iva_retenido': 0.00,
                    'amount': round(amount_neto, 2)
                }
            }
        return result

    def onchange_is_iva(self,
                        cr,
                        uid,
                        ids,
                        tipo_comp,
                        is_iva,
                        amount_neto,
                        por_iva,
                        context=None):
        result = {}
        print "TIPO COMP", tipo_comp
        print "IS IVA", is_iva
        print "SUBTOTAL", amount_neto
        iva = int(por_iva)

        if tipo_comp == 'factura' and is_iva:
            result = {
                'value': {
                    'amount_iva_retenido': round((amount_neto * iva) / 100, 2),
                    'amount': round(amount_neto + ((amount_neto * iva) / 100),
                                    2)
                }
            }
        elif tipo_comp == 'factura' and not is_iva:
            result = {
                'value': {
                    'amount_iva_retenido': 0.00,
                    'amount': round(amount_neto, 2)
                }
            }
        else:
            result = {
                'value': {
                    'amount_iva_retenido': 0.00,
                    'amount': round(amount_neto, 2)
                }
            }
        return result

    def onchange_valor_proc(self,
                            cr,
                            uid,
                            ids,
                            tipo_comp,
                            amount,
                            context=None):
        result = {}
        print "amount", amount
        amount_conc = amount
        print "amount_conc", amount_conc
        if tipo_comp != 'factura':
            result = {
                'value': {
                    'amount_iva_retenido': 0.00,
                    'amount_neto': round(amount, 2)
                }
            }
        else:
            result = {
                'value': {
                    'amount_iva_retenido': round((amount * 14) / 100, 2),
                    'amount_neto': round(amount - ((amount * 14) / 100), 2)
                }
            }
        return result
Example #52
0
                '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,
    }

    def grid_get(self, cr, uid, ids, contact_id, context=None):
        contact = self.pool.get('res.partner').browse(cr, uid, contact_id, context=context)
        for carrier in self.browse(cr, uid, ids, context=context):
    
    def _get_uom_id(self, cr, uid, context=None):
        try:
            proxy = self.pool.get('ir.model.data')
            result = proxy.get_object_reference(cr, uid, 'product', 'product_uom_unit')
            return result[1]
        except Exception, ex:
            return False
    
    _columns = {
        
#        'location_destination_id': fields.many2one('stock.location', 'Stock Destination Location'),
#        'location_id': fields.many2one('stock.location', 'Stock Source Location'),
        'product_id': fields.many2one('product.product', 'Product'),
        'back_order_id': fields.many2one('back.to.back.order', 'Back Order'),
        'qty': fields.float('Quantity'),
        'price': fields.float('Unit Price'),
        'subtotal': fields.function(_amount_line, string='Subtotal', digits_compute= dp.get_precision('Account')),
        'taxes_id': fields.many2many('account.tax', 'purchase_order_taxe', 'ord_id', 'tax_id', 'Taxes'),
        'product_uom': fields.many2one('product.uom', 'Product Unit of Measure', required=True),
        
           
    }
    
    
    _defaults = {
        'product_uom' : _get_uom_id,
    }

# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: