class hr_warning(models.Model): _name = 'hr.infraction.warning' _description = 'Employee Warning' _columns = { 'name': fields.char( 'Subject', size=256, ), 'date': fields.date( 'Date Issued', ), 'type': fields.selection( [ ('verbal', 'Verbal'), ('written', 'Written'), ], 'Type', required=True, ), 'action_id': fields.many2one( 'hr.infraction.action', 'Action', ondelete='cascade', readonly=True, ), 'infraction_id': fields.related( 'action_id', 'infraction_id', type='many2one', obj='hr.infraction', string='Infraction', readonly=True, ), 'employee_id': fields.related( 'infraction_id', 'employee_id', type='many2one', obj='hr.employee', string='Employee', readonly=True, ), } _defaults = { 'type': 'written', 'date': time.strftime(DEFAULT_SERVER_DATE_FORMAT), } def unlink(self, cr, uid, ids, context=None): for warning in self.browse(cr, uid, ids, context=context): if (warning.action_id and warning.action_id.infraction_id.state != 'draft'): raise models.except_orm( _('Error'), _('Warnings attached to Infractions not in "Draft" state ' 'may not be removed.') ) return super(hr_warning, self).unlink(cr, uid, ids, context=context)
class patient_data (osv.osv): _name = "medical.patient" _inherit = "medical.patient" _columns = { 'receivable' : fields.related('name','credit',type='float',string='Receivable',help='Total amount this patient owes you',readonly=True), }
class pos_stock_inventory_categ_detail_line(osv.osv): _name = 'pos.stock.inventory.categ.detail.line' _description = 'Detalle del Inventario por Categoria' _rec_name = 'product_id' _columns = { 'ref_id': fields.many2one('pos.stock.inventory.categ.detail', 'ID Ref'), 'location_id': fields.many2one( 'stock.location', 'Ubicacion', ), 'product_id': fields.many2one('product.product', 'Producto'), 'product_uom_id': fields.many2one( 'product.uom', 'Unidad Base', ), 'product_qty': fields.float('Cantidad', digits=(14, 2)), 'default_code': fields.related('product_id', 'default_code', type='char', string='Codigo Interno', readonly=True), } _defaults = {} _order = 'id'
class stock_move(osv.osv): _inherit = 'stock.move' _columns = { 'default_code': fields.related('product_id', 'default_code', type='char', string='Internal Reference'), }
class sale_order_line(osv.osv): _inherit = 'sale.order.line' _columns = { 'default_code': fields.related('product_id', 'default_code', type='char', string='Internal Reference'), }
class account_invoice_line(osv.osv): _inherit = 'account.invoice.line' _columns = { 'default_code': fields.related('product_id', 'default_code', type='char', string='Internal Reference'), }
class hr_infraction_action(models.Model): _name = 'hr.infraction.action' _description = 'Action Based on Infraction' _columns = { 'infraction_id': fields.many2one( 'hr.infraction', 'Infraction', ondelete='cascade', required=True, readonly=True, ), 'type': fields.selection( ACTION_TYPE_SELECTION, 'Type', required=True, ), 'memo': fields.text( 'Notes', ), 'employee_id': fields.related( 'infraction_id', 'employee_id', type='many2one', store=True, obj='hr.employee', string='Employee', readonly=True, ), 'warning_id': fields.many2one( 'hr.infraction.warning', 'Warning', readonly=True, ), 'transfer_id': fields.many2one( 'hr.department.transfer', 'Transfer', readonly=True, ), } _rec_name = 'type' def unlink(self, cr, uid, ids, context=None): for action in self.browse(cr, uid, ids, context=context): if action.infraction_id.state not in ['draft']: raise models.except_orm( _('Error'), _('Actions belonging to Infractions not in "Draft" state ' 'may not be removed.') ) return super(hr_infraction_action, self).unlink( cr, uid, ids, context=context )
class hr_contract(models.Model): _name = 'hr.contract' _inherit = 'hr.contract' _columns = { 'is_labour_union': fields.related( 'employee_id', 'is_labour_union', type='boolean', store=True, string='Labour Union Member', ), }
class stock_inventory_line(osv.osv): _name = 'stock.inventory.line' _inherit = 'stock.inventory.line' _columns = { 'product_category': fields.related('product_id', 'categ_id', type="many2one", relation="product.category", string='Categoria', store=True), } _defaults = {}
class custom_calendar_event(osv.osv): _name = "calendar.event" _inherit = 'calendar.event' @api.depends('x_categ_id','x_partner_id') def _compute_categ_id_char(self): self.x_categ_id_char = self.x_categ_id.name if self.x_categ_id_char and self.x_partner_id.display_name and self.x_partner_id.phone: self.name = self.x_categ_id_char+' : '+self.x_partner_id.display_name+', '+self.x_partner_id.phone elif self.x_categ_id_char and self.x_partner_id.display_name: self.name = self.x_categ_id_char+' : '+self.x_partner_id.display_name elif self.x_partner_id.display_name: self.name = self.x_partner_id.display_name elif self.x_categ_id_char: self.name = self.x_categ_id_char else: _columns = { 'x_domicile': fields.boolean('A domicile'), 'x_partner_id': fields.many2one('res.partner', 'Attendee', default=''), 'x_categ_id': fields.many2one('calendar.event.type', 'Tags'), 'x_categ_id_char': fields.char(compute='_compute_categ_id_char', default=''), 'x_event_is_billed': fields.boolean('is_billed'), 'x_event_is_printed': fields.boolean('is_printed'), # related field res.partner # ------------------------- 'x_event_display_name' : fields.related('x_partner_id', 'display_name', type="char"), 'x_event_name' : fields.related('x_partner_id', 'name', type="char"), 'x_event_phone' : fields.related('x_partner_id', 'phone', type="char", default=''), 'x_event_patient_prenom': fields.related('x_partner_id', 'x_patient_prenom', type="char"), 'x_event_patient_sexe': fields.related('x_partner_id', 'x_patient_sexe', type="selection", selection=SEXE_SELECTION), 'x_event_patient_cafat': fields.related('x_partner_id', 'x_patient_cafat', type="char"), 'x_event_dob': fields.date(related='x_partner_id.dob'), 'x_event_age' : fields.integer(related='x_partner_id.age'), 'x_event_src_avatar' : fields.binary(related='x_partner_id.x_src_avatar'), 'x_event_medecin_traitant': fields.char(related='x_partner_id.x_medecin_traitant'), ########## MEDICAL INFO ??? # 'x_event_groupe_sang': fields.related('x_partner_id', 'x_groupe_sang', type="selection", selection=GRP_SANG_SELECTION), # 'x_event_taille': fields.float(related='x_partner_id.x_taille'), # 'x_event_poids': fields.float(related='x_partner_id.x_poids'), # 'x_event_IMC': fields.float(related='x_partner_id.x_IMC'), ########## # related field calendar_event_type # ------------------------- 'x_event_codeActe': fields.char(related='x_categ_id.x_code_acte', size=8), 'x_event_priceActe': fields.float(related='x_categ_id.x_price_acte', digits=(4,0)), # ------------------------- } _default = { 'x_domicile': False, }
class stock_move(osv.osv): _inherit = 'stock.move' _columns = { 'picking_type_code': fields.related('picking_type_id', 'code', type='char', string='Picking Type Code', help="Technical field used to display the correct label on print button in the picking view"), 'location_dest_asset': fields.related('location_dest_id', 'asset_location', type='boolean', string='Destination Asset Location', readonly="1"), 'location_asset': fields.related('location_id', 'asset_location', type='boolean', string='Source Asset Location', readonly="1"), 'asset_category_id': fields.many2one('account.asset.category', "Asset Category", domain=[('asset_type','=','fixed')]), 'asset_id': fields.many2one('account.asset.asset', "Asset"), 'asset_ids': fields.one2many('account.asset.asset', 'stock_move_id', "Assets", readonly="1"), } def onchange_picking_type_id(self, cr, uid, ids, picking_type_id=False, context=None): if not picking_type_id: return {} res = {} pick_type = self.pool.get('stock.picking.type').browse(cr, uid, picking_type_id, context=context) res['picking_type_code'] = str(pick_type.code) return {'value': res} def onchange_location_asset(self, cr, uid, ids, location_id=False, context=None): if not location_id: return {} res = {} location = self.pool.get('stock.location').browse(cr, uid, location_id, context=context) res['location_asset'] = location.asset_location return {'value': res} def onchange_location_dest_asset(self, cr, uid, ids, location_dest_id=False, context=None): if not location_dest_id: return {} res = {} location = self.pool.get('stock.location').browse(cr, uid, location_dest_id, context=context) res['location_dest_asset'] = location.asset_location return {'value': res} def onchange_asset_category_id(self, cr, uid, ids, asset_category_id=False, pick_type_id=False, context=None): if not asset_category_id: return {} res = {} if pick_type_id: pick_type = self.pool.get('stock.picking.type').browse(cr, uid, pick_type_id, context=context) dest_location_id = pick_type.warehouse_id and pick_type.warehouse_id.wh_asset_loc_id and pick_type.warehouse_id.wh_asset_loc_id.id or False res['location_dest_id'] = dest_location_id return {'value': res} def action_done(self, cr, uid, ids, context=None): super(stock_move, self).action_done(cr, uid, ids, context) context = context or {} asset_obj = self.pool.get('account.asset.asset') for move in self.browse(cr, uid, ids, context=context): if move.asset_category_id and not move.asset_ids: purchase_date = move.date partner_id = move.partner_id and move.partner_id.id or False purchase_value = move.price_unit category_id = move.asset_category_id if category_id.prorata: purchase_date = move.date else: purchase_date = datetime.strptime(move.date[:10],"%Y-%m-%d") + relativedelta(day=1, months=+1) vals = { 'name': move.product_id.name, 'category_id': category_id.id, 'asset_type': category_id.asset_type, 'code': move.product_id.name or False, 'purchase_value': purchase_value, 'inventory_value' : purchase_value, 'purchase_date': purchase_date, 'partner_id': partner_id, 'entry_date': move.date, 'product_id': move.product_id.id, 'stock_move_id': move.id, 'picking_id':move.picking_id and move.picking_id.id or False, 'state': 'draft', } if move.quant_ids: for quant in move.quant_ids: lot_id = quant.lot_id and quant.lot_id.id or False vals['prodlot_id'] = lot_id qty = quant.qty while qty > 0: qty -= 1 changed_vals = asset_obj.onchange_category_id(cr, uid, [], vals['category_id'], context=context) vals.update(changed_vals['value']) asset_id = asset_obj.create(cr, uid, vals, context=context) return True def action_cancel(self, cr, uid, ids, context=None): """ Try to cancel the assets linked with this stock move if they are in draft state """ context = context or {} for move in self.browse(cr, uid, ids, context=context): if move.asset_category_id and move.asset_ids: for asset in move.asset_ids: if asset.state <> 'draft': raise except_orm(_('Error!'), _("You cannot cancel a stock move which doesn't have assets in draft state. You need to reset to draft the asset with name %s." % asset.name)) move.asset_ids.unlink() return super(stock_move, self).action_cancel(cr, uid, ids, context=context) def action_assign(self, cr, uid, ids, context=None): """ Checks the product type and accordingly writes the state. """ context = context or {} quant_obj = self.pool.get("stock.quant") to_assign_moves = [] main_domain = {} todo_moves = [] operations = set() for move in self.browse(cr, uid, ids, context=context): if move.asset_id: if move.state not in ('confirmed', 'waiting', 'assigned'): continue if move.location_id.usage in ('supplier', 'inventory', 'production'): to_assign_moves.append(move.id) #in case the move is returned, we want to try to find quants before forcing the assignment if not move.origin_returned_move_id: continue if move.product_id.type == 'consu': to_assign_moves.append(move.id) continue else: todo_moves.append(move) #we always keep the quants already assigned and try to find the remaining quantity on quants not assigned only main_domain[move.id] = [('history_ids', 'in', move.asset_id.stock_move_id.id),('reservation_id', '=', False), ('qty', '>', 0)] #if the move is preceeded, restrict the choice of quants in the ones moved previously in original move ancestors = self.find_move_ancestors(cr, uid, move, context=context) if move.state == 'waiting' and not ancestors: #if the waiting move hasn't yet any ancestor (PO/MO not confirmed yet), don't find any quant available in stock main_domain[move.id] += [('id', '=', False)] elif ancestors: main_domain[move.id] += [('history_ids', 'in', ancestors)] #if the move is returned from another, restrict the choice of quants to the ones that follow the returned move if move.origin_returned_move_id: main_domain[move.id] += [('history_ids', 'in', move.origin_returned_move_id.id)] for link in move.linked_move_operation_ids: operations.add(link.operation_id) # Check all ops and sort them: we want to process first the packages, then operations with lot then the rest operations = list(operations) operations.sort(key=lambda x: ((x.package_id and not x.product_id) and -4 or 0) + (x.package_id and -2 or 0) + (x.lot_id and -1 or 0)) for ops in operations: #first try to find quants based on specific domains given by linked operations for record in ops.linked_move_operation_ids: move = record.move_id if move.id in main_domain: domain = main_domain[move.id] + self.pool.get('stock.move.operation.link').get_specific_domain(cr, uid, record, context=context) qty = record.qty if qty: quants = quant_obj.quants_get_prefered_domain(cr, uid, ops.location_id, move.product_id, qty, domain=domain, prefered_domain_list=[], restrict_lot_id=move.restrict_lot_id.id, restrict_partner_id=move.restrict_partner_id.id, context=context) quant_obj.quants_reserve(cr, uid, quants, move, record, context=context) for move in todo_moves: move.refresh() #then if the move isn't totally assigned, try to find quants without any specific domain if move.state != 'assigned': qty_already_assigned = move.reserved_availability qty = move.product_qty - qty_already_assigned quants = quant_obj.quants_get_prefered_domain(cr, uid, move.location_id, move.product_id, qty, domain=main_domain[move.id], prefered_domain_list=[], restrict_lot_id=move.restrict_lot_id.id, restrict_partner_id=move.restrict_partner_id.id, context=context) quant_obj.quants_reserve(cr, uid, quants, move, context=context) #force assignation of consumable products and incoming from supplier/inventory/production if to_assign_moves: self.force_assign(cr, uid, to_assign_moves, context=context) else: super(stock_move, self).action_assign(cr, uid, ids, context=context)
class AccountVoucher(osv.osv): _inherit = "account.voucher" @api.one @api.depends('currency_id', 'payment_rate_currency_id', 'payment_rate', 'amount', 'date', 'journal_id') def _compute_rate_amount(self): print "--_compute_rate_amount-" if self.currency_id != self.payment_rate_currency_id: currency_obj = self.env['res.currency'] currency_str = payment_rate_str = '' if self.currency_id: currency_str = currency_obj.browse(self.currency_id.id) if self.payment_rate_currency_id: payment_rate_str = currency_obj.browse(self.payment_rate_currency_id.id) #currency_payment = currency_obj.browse(self.currency_id.id)#.rate amount_curr = u'%s\N{NO-BREAK SPACE}%s' % (currency_str.symbol, locale.format("%d", payment_rate_str.rate, grouping=True))#formatLang(self.env, currency_payment.rate, currency_obj=self.currency_id) amount_curr_payment = u'%s\N{NO-BREAK SPACE}%s' % (payment_rate_str.symbol, locale.format("%d", currency_str.rate, grouping=True)) #print "====",self.date,currency_str.rate,payment_rate_str.rate currency_help_label = _('The exchange rate was %s = %s') % (amount_curr, amount_curr_payment) self.amount_info = self.amount * currency_str.rate self.currency_inverse_help_label = currency_help_label def _get_currency_help_label(self, cr, uid, currency_id, payment_rate, payment_rate_currency_id, context=None): rml_parser = report_sxw.rml_parse(cr, uid, 'currency_help_label', context=context) currency_pool = self.pool.get('res.currency') currency_str = payment_rate_str = '' if currency_id: currency_str = rml_parser.formatLang(1, currency_obj=currency_pool.browse(cr, uid, currency_id, context=context)) if payment_rate_currency_id: payment_rate_str = rml_parser.formatLang(currency_pool.browse(cr, uid, currency_id, context=context).rate, currency_obj=currency_pool.browse(cr, uid, payment_rate_currency_id, context=context)) currency_help_label = _('At the operation date, the exchange rate was\n%s = %s') % (currency_str, payment_rate_str) return currency_help_label def _fnct_currency_help_label(self, cr, uid, ids, name, args, context=None): res = {} for voucher in self.browse(cr, uid, ids, context=context): res[voucher.id] = self._get_currency_help_label(cr, uid, voucher.currency_id.id, voucher.payment_rate, voucher.company_currency_id.id, context=context) return res def _get_amount_help_label(self, cr, uid, currency_id, payment_rate, payment_rate_currency_id, context=None): # rml_parser = report_sxw.rml_parse(cr, uid, 'currency_help_label', context=context) currency_pool = self.pool.get('res.currency') # currency_str = payment_rate_str = '' if currency_id: #print "=======",currency_pool.browse(cr, uid, currency_id, context=context).rate # currency_str = rml_parser.formatLang(1, currency_obj=currency_pool.browse(cr, uid, currency_id, context=context)) # if payment_rate_currency_id: # payment_rate_str = rml_parser.formatLang(currency_pool.browse(cr, uid, currency_id, context=context).rate, currency_obj=currency_pool.browse(cr, uid, payment_rate_currency_id, context=context)) # currency_help_label = _('At the operation date, the exchange rate was\n%s = %s') % (currency_str, payment_rate_str) return str(payment_rate*currency_pool.browse(cr, uid, currency_id, context=context).rate) def _fnct_amount_info_label(self, cr, uid, ids, name, args, context=None): res = {} for voucher in self.browse(cr, uid, ids, context=context): res[voucher.id] = self._get_amount_help_label(cr, uid, voucher.currency_id.id, voucher.amount, voucher.company_currency_id.id, context=context) return res _columns = { 'is_currency': fields.boolean('Is multi currency'), 'amount_info': fields.function(_fnct_amount_info_label, type='float', string='Amount Rate'), 'currency_inverse_help_label': fields.text('Rate'), 'company_currency_id': fields.related('company_id','currency_id', type='many2one', relation='res.currency', string='Company Currency'), 'currency_help_label': fields.function(_fnct_currency_help_label, type='text', string="Helping Sentence", help="This sentence helps you to know how to specify the payment rate by giving you the direct effect it has"), } # is_currency = fields.Boolean('Is multi currency') # amount_info = fields.Float(string='Amount Rate', compute='_compute_rate_amount') # currency_inverse_help_label = fields.Text(string='Helping Rate Sentence', compute='_compute_rate_amount') def onchange_rate(self, cr, uid, ids, rate, amount, currency_id, payment_rate_currency_id, company_id, context=None): company_currency = self.pool.get('res.company').browse(cr, uid, company_id, context=context).currency_id #currency_pool = self.pool.get('res.currency') #rate_view = currency_pool.browse(cr, uid, currency_id, context=context).rate #print "==onchange_rate==",amount,rate,rate_view,amount*rate_view res = {'value': {'paid_amount_in_company_currency': amount, 'amount_info': self._get_amount_help_label(cr, uid, currency_id, amount, company_currency.id, context=context), 'currency_help_label': self._get_currency_help_label(cr, uid, currency_id, rate, payment_rate_currency_id, context=context)}} if rate and amount and currency_id: company_currency = self.pool.get('res.company').browse(cr, uid, company_id, context=context).currency_id #context should contain the date, the payment currency and the payment rate specified on the voucher amount_in_company_currency = self.pool.get('res.currency').compute(cr, uid, currency_id, company_currency.id, amount, context=context) res['value']['paid_amount_in_company_currency'] = amount_in_company_currency return res def onchange_journal(self, cr, uid, ids, journal_id, line_ids, tax_id, partner_id, date, amount, ttype, company_id, context=None): if context is None: context = {} if not journal_id: return False journal_pool = self.pool.get('account.journal') journal = journal_pool.browse(cr, uid, journal_id, context=context) if ttype in ('sale', 'receipt'): account_id = journal.default_debit_account_id elif ttype in ('purchase', 'payment'): account_id = journal.default_credit_account_id else: account_id = journal.default_credit_account_id or journal.default_debit_account_id tax_id = False if account_id and account_id.tax_ids: tax_id = account_id.tax_ids[0].id vals = {'value':{} } if ttype in ('sale', 'purchase'): vals = self.onchange_price(cr, uid, ids, line_ids, tax_id, partner_id, context) vals['value'].update({'tax_id':tax_id,'amount': amount}) currency_id = False if journal.currency: currency_id = journal.currency.id else: currency_id = journal.company_id.currency_id.id period_ids = self.pool['account.period'].find(cr, uid, dt=date, context=dict(context, company_id=company_id)) is_currency = False if journal.currency.id and journal.currency.id != journal.company_id.currency_id.id: is_currency = True #print "===is_currency====",is_currency,journal.currency.id,journal.company_id.currency_id.id vals['value'].update({ 'currency_id': currency_id, 'payment_rate_currency_id': currency_id, 'is_currency': is_currency, 'period_id': period_ids and period_ids[0] or False }) #in case we want to register the payment directly from an invoice, it's confusing to allow to switch the journal #without seeing that the amount is expressed in the journal currency, and not in the invoice currency. So to avoid #this common mistake, we simply reset the amount to 0 if the currency is not the invoice currency. if context.get('payment_expected_currency') and currency_id != context.get('payment_expected_currency'): vals['value']['amount'] = 0 amount = 0 if partner_id: res = self.onchange_partner_id(cr, uid, ids, partner_id, journal_id, amount, currency_id, ttype, date, context) for key in res.keys(): vals[key].update(res[key]) return vals
class custom_stock_serial(osv.osv): _inherit = 'stock.production.lot' _columns = { 'company': fields.related('product_id', 'company_id', relation="res.company", type='many2one', string="Company", store=True), 'status': fields.selection([('Available', 'Available'), ('Issued', 'Issued')], string='Status', store=True), 'chassis_number': fields.char('Chassis No.', store=True), 'color': fields.char('Color', store=True, compute='fetch_color'), 'model': fields.char(string='Model', store=True), 'year': fields.selection([ ('2010', '2010'), ('2011', '2011'), ('2012', '2012'), ('2013', '2013'), ('2014', '2014'), ('2015', '2015'), ('2016', '2016'), ('2017', '2017'), ('2018', '2018'), ('2019', '2019'), ('2020', '2020'), ('2021', '2021'), ('2022', '2022'), ('2023', '2023'), ('2024', '2024'), ('2025', '2025'), ('2026', '2026'), ('2027', '2027'), ], string='Year', store=True), } _defaults = { 'status': 'Available', 'name': 'SAE-', 'chassis_number': 'SAC-', 'model': '70 CC', 'year': '2018' } @api.constrains('name') def _check_unique_constraint(self): if len( self.search([('name', '=', self.name), ('company', '=', self.company.id)])) > 1: raise ValidationError( "This engine number already exists and violates unique field constraint" ) @api.constrains('chassis_number') def _check_unique_constraint_(self): if len( self.search([('name', '=', self.name), ('company', '=', self.company.id)])) > 1: raise ValidationError( "This chassis number already exists and violates unique field constraint" ) @api.one @api.depends('product_id') def fetch_color(self): products = [ 1856, 1850, 1851, 1852, 1853, 1854, 1855, 1857, 1858, 1862, 1980, 1981, 1982, 1983, 1984, 1985, 1986, 1987 ] if self.product_id and self.product_id.id in products: color = '' attribute = ( self.product_id.attribute_value_ids[0].name).split(' ') if attribute[0] == 'Durbi' or attribute[0] == 'Smart' or attribute[ 0] == 'Self': for _color in attribute: color += _color + " " self.color = color
class hr_transfer(models.Model): _name = 'hr.department.transfer' _description = 'Departmental Transfer' _inherit = ['mail.thread', 'ir.needaction_mixin'] _columns = { 'employee_id': fields.many2one('hr.employee', 'Employee', required=True, readonly=True, states={'draft': [('readonly', False)]}), 'src_id': fields.many2one('hr.job', 'From', required=True, readonly=True, states={'draft': [('readonly', False)]}), 'dst_id': fields.many2one('hr.job', 'Destination', required=True, readonly=True, states={'draft': [('readonly', False)]}), 'src_department_id': fields.related('src_id', 'department_id', type='many2one', relation='hr.department', string='From Department', store=True, readonly=True), 'dst_department_id': fields.related('dst_id', 'department_id', type='many2one', relation='hr.department', store=True, string='Destination Department', readonly=True), 'src_contract_id': fields.many2one('hr.contract', 'From Contract', readonly=True, states={'draft': [('readonly', False)]}), 'dst_contract_id': fields.many2one('hr.contract', 'Destination Contract', readonly=True), 'date': fields.date('Effective Date', required=True, readonly=True, states={'draft': [('readonly', False)]}), 'state': fields.selection([ ('draft', 'Draft'), ('confirm', 'Confirmed'), ('pending', 'Pending'), ('done', 'Done'), ('cancel', 'Cancelled'), ], 'State', readonly=True), } _rec_name = 'date' _defaults = { 'state': 'draft', } _track = { 'state': { 'hr_transfer.mt_alert_xfer_confirmed': lambda self, cr, uid, obj, ctx=None: obj['state'] == 'confirm', 'hr_transfer.mt_alert_xfer_pending': lambda self, cr, uid, obj, ctx=None: obj['state'] == 'pending', 'hr_transfer.mt_alert_xfer_done': lambda self, cr, uid, obj, ctx=None: obj['state'] == 'done', }, } def _needaction_domain_get(self, cr, uid, context=None): users_obj = self.pool.get('res.users') if users_obj.has_group(cr, uid, 'base.group_hr_manager'): domain = [('state', '=', 'confirm')] return domain return False def unlink(self, cr, uid, ids, context=None): for xfer in self.browse(cr, uid, ids, context=context): if xfer.state not in ['draft']: raise models.except_orm( _('Unable to Delete Transfer!'), _('Transfer has been initiated. Either cancel the transfer' ' or create another transfer to undo it.')) return super(hr_transfer, self).unlink(cr, uid, ids, context=context) def onchange_employee(self, cr, uid, ids, employee_id, context=None): res = {'value': {'src_id': False, 'src_contract_id': False}} if employee_id: ee = self.pool.get('hr.employee').browse(cr, uid, employee_id, context=context) res['value']['src_id'] = ee.contract_id.job_id.id res['value']['src_contract_id'] = ee.contract_id.id return res def effective_date_in_future(self, cr, uid, ids, context=None): today = datetime.now().date() for xfer in self.browse(cr, uid, ids, context=context): effective_date = datetime.strptime( xfer.date, DEFAULT_SERVER_DATE_FORMAT).date() if effective_date <= today: return False return True def _check_state(self, cr, uid, contract_id, effective_date, context=None): contract_obj = self.pool.get('hr.contract') data = contract_obj.read(cr, uid, contract_id, ['state', 'date_end'], context=context) if data['state'] not in [ 'trial', 'trial_ending', 'open', 'contract_ending' ]: raise models.except_orm( _('Warning!'), _('The current state of the contract does not permit changes.') ) if data.get('date_end', False) and data['date_end'] != '': dContractEnd = datetime.strptime(data['date_end'], DEFAULT_SERVER_DATE_FORMAT) dEffective = datetime.strptime(effective_date, DEFAULT_SERVER_DATE_FORMAT) if dEffective >= dContractEnd: raise models.except_orm( _('Warning!'), _('The contract end date is on or before the effective ' 'date of the transfer.')) return True def transfer_contract(self, cr, uid, contract_id, job_id, xfer_id, effective_date, context=None): contract_obj = self.pool.get('hr.contract') # Copy the contract and adjust start/end dates, job id, etc. # accordingly. # default = { 'job_id': job_id, 'date_start': effective_date, 'name': False, 'state': False, 'message_ids': False, 'trial_date_start': False, 'trial_date_end': False, } data = contract_obj.copy_data(cr, uid, contract_id, default=default, context=context) c_id = contract_obj.create(cr, uid, data, context=context) if c_id: vals = {} wkf = netsvc.LocalService('workflow') # Set the new contract to the appropriate state wkf.trg_validate(uid, 'hr.contract', c_id, 'signal_confirm', cr) # Terminate the current contract (and trigger appropriate state # change) vals['date_end'] = datetime.strptime( effective_date, '%Y-%m-%d').date() + relativedelta(days=-1) contract_obj.write(cr, uid, contract_id, vals, context=context) wkf.trg_validate(uid, 'hr.contract', contract_id, 'signal_done', cr) # Link to the new contract self.pool.get('hr.department.transfer').write( cr, uid, xfer_id, {'dst_contract_id': c_id}, context=context) return def state_confirm(self, cr, uid, ids, context=None): for xfer in self.browse(cr, uid, ids, context=context): self._check_state(cr, uid, xfer.src_contract_id.id, xfer.date, context=context) self.write(cr, uid, xfer.id, {'state': 'confirm'}, context=context) return True def state_done(self, cr, uid, ids, context=None): employee_obj = self.pool.get('hr.employee') today = datetime.now().date() for xfer in self.browse(cr, uid, ids, context=context): if datetime.strptime(xfer.date, DEFAULT_SERVER_DATE_FORMAT).date() <= today: self._check_state(cr, uid, xfer.src_contract_id.id, xfer.date, context=context) employee_obj.write( cr, uid, xfer.employee_id.id, {'department_id': xfer.dst_department_id.id}, context=context) self.transfer_contract(cr, uid, xfer.src_contract_id.id, xfer.dst_id.id, xfer.id, xfer.date, context=context) self.write(cr, uid, xfer.id, {'state': 'done'}, context=context) else: return False return True def try_pending_department_transfers(self, cr, uid, context=None): """Completes pending departmental transfers. Called from the scheduler.""" xfer_obj = self.pool.get('hr.department.transfer') today = datetime.now().date() xfer_ids = xfer_obj.search( cr, uid, [ ('state', '=', 'pending'), ('date', '<=', today.strftime(DEFAULT_SERVER_DATE_FORMAT)), ], context=context) wkf = netsvc.LocalService('workflow') [ wkf.trg_validate(uid, 'hr.department.transfer', xfer.id, 'signal_done', cr) for xfer in self.browse(cr, uid, xfer_ids, context=context) ] return True
class wage_increment(models.Model): _name = 'hr.contract.wage.increment' _description = 'HR Contract Wage Adjustment' def _calculate_difference(self, cr, uid, ids, field_name, args, context=None): res = dict.fromkeys(ids) for incr in self.browse(cr, uid, ids, context=context): if incr.wage >= incr.contract_id.wage: percent = ((incr.wage / incr.contract_id.wage) - 1.0) * 100.0 else: percent = (1.0 - (incr.wage / incr.contract_id.wage)) * -100.0 res[incr.id] = { 'wage_difference': incr.wage - incr.current_wage, 'wage_difference_percent': percent, } return res def _get_department(self, cr, uid, ids, field_name, arg, context=None): res = dict.fromkeys(ids, False) for incr in self.browse(cr, uid, ids, context=context): res[incr.id] = incr.employee_id.department_id.id, return res _columns = { 'effective_date': fields.date( 'Effective Date', required=True, readonly=True, states={'draft': [('readonly', False)]}, ), 'wage': fields.float( 'New Wage', digits_compute=dp.get_precision('Payroll'), required=True, readonly=True, states={'draft': [('readonly', False)]}, ), 'new_contract_id': fields.many2one( 'hr.contract', 'New Contract', readonly=True, ), 'contract_id': fields.many2one( 'hr.contract', 'Contract', readonly=True, ), 'current_wage': fields.related( 'contract_id', 'wage', type='float', string='Current Wage', store=True, readonly=True, ), 'wage_difference': fields.function( _calculate_difference, type='float', method=True, string='Difference', multi='diff', readonly=True, ), 'wage_difference_percent': fields.function( _calculate_difference, type='float', method=True, string='Percentage', multi='diff', readonly=True, ), 'employee_id': fields.related( 'contract_id', 'employee_id', relation='hr.employee', type='many2one', string='Employee', store=True, readonly=True, ), 'job_id': fields.related( 'contract_id', 'job_id', relation='hr.job', type='many2one', string='Job', store=True, readonly=True, ), 'department_id': fields.related( 'employee_id', 'department_id', relation='hr.department', type='many2one', string='Department', store=True, readonly=True, ), 'state': fields.selection( [('draft', 'Draft'), ('confirm', 'Confirmed'), ('approve', 'Approved'), ('decline', 'Declined')], 'State', readonly=True, ), 'run_id': fields.many2one( 'hr.contract.wage.increment.run', 'Batch Run', readonly=True, ondelete='cascade', ), } def _get_contract_data(self, cr, uid, field_list, context=None): if context is None: context = {} employee_id = self._get_employee(cr, uid, context=context) ee_data = self.pool.get('hr.employee').read(cr, uid, employee_id, ['contract_id'], context=context) contract_id = ee_data.get('contract_id', False)[0] if not contract_id: return False data = self.pool.get('hr.contract').read(cr, uid, contract_id, field_list, context=context) return data def _get_contract_id(self, cr, uid, context=None): data = self._get_contract_data(cr, uid, ['id'], context) return data.get('id', False) def _get_employee(self, cr, uid, context=None): if context is None: context = {} employee_id = context.get('active_id', False) return employee_id def _get_effective_date(self, cr, uid, context=None): contract_id = self._get_contract_id(cr, uid, context=context) if not contract_id: return False contract = self.pool.get('hr.contract').browse(cr, uid, contract_id, context=context) if contract.pps_id: first_day = 1 if contract.pps_id.type == 'monthly': first_day = contract.pps_id.mo_firstday date_format = '%Y-%m-' + first_day dThisMonth = datetime.now().strftime(date_format).strptime( DEFAULT_SERVER_DATE_FORMAT).date() dNextMonth = (datetime.now() + relativedelta(months=+1)).strftime( date_format).strptime(DEFAULT_SERVER_DATE_FORMAT).date() if dThisMonth < datetime.now().date(): return dNextMonth.strftime(DEFAULT_SERVER_DATE_FORMAT) else: return dThisMonth.strftime(DEFAULT_SERVER_DATE_FORMAT) return False _defaults = { 'contract_id': _get_contract_id, 'employee_id': _get_employee, 'effective_date': _get_effective_date, 'state': 'draft', } _rec_name = 'effective_date' def _check_state(self, cr, uid, wage_incr, context=None): wage_incr_ids = self.search( cr, uid, [ ('contract_id', '=', wage_incr.contract_id.id), ('state', 'in', ['draft', 'confirm', 'approved']), ('id', '!=', wage_incr.id), ], context=context) if len(wage_incr_ids) > 0: data = self.pool.get('hr.contract').read(cr, uid, wage_incr.contract_id.id, ['name'], context=context) raise models.except_orm( _('Warning'), _('There is already another wage adjustment in progress for ' 'this contract: %s.') % (data['name'])) contract_obj = self.pool.get('hr.contract') data = contract_obj.read(cr, uid, wage_incr.contract_id.id, ['state', 'date_end'], context=context) if data['state'] in ['draft', 'done']: data = self.pool.get('hr.contract').read(cr, uid, wage_incr.contract_id.id, ['name'], context=context) raise models.except_orm( _('Warning!'), _('The current state of the contract does not permit a wage ' 'change: %s') % (data['name'])) if data.get('date_end', False) and data['date_end'] != '': dContractEnd = datetime.strptime(data['date_end'], DEFAULT_SERVER_DATE_FORMAT) dEffective = datetime.strptime(wage_incr.effective_date, DEFAULT_SERVER_DATE_FORMAT) if dEffective >= dContractEnd: data = self.pool.get('hr.contract').read( cr, uid, wage_incr.contract_id.id, ['name'], context=context) raise models.except_orm( _('Warning!'), _('The contract end date is on or before the effective ' 'date of the adjustment: %s') % (data['name'])) return True def action_wage_increment(self, cr, uid, ids, context=None): hr_obj = self.pool.get('hr.contract') if isinstance(ids, (int, long)): ids = [ids] # Copy the contract and adjust start/end dates and wage accordingly. # for wi in self.browse(cr, uid, ids, context=context): if -0.01 < wi.wage_difference < 0.01: continue self._check_state(cr, uid, wi, context=context) default = { 'wage': wi.wage, 'date_start': wi.effective_date, 'name': False, 'state': False, 'message_ids': False, 'trial_date_start': False, 'trial_date_end': False, } data = hr_obj.copy_data(cr, uid, wi.contract_id.id, default=default, context=context) notes = data.get('notes', False) if not notes: notes = '' notes = notes + \ _('\nSuperceedes (because of wage adjustment) previous ' 'contract: ') + wi.contract_id.name data['notes'] = notes c_id = hr_obj.create(cr, uid, data, context=context) if c_id: if wi.contract_id.notes: notes = wi.contract_id.notes else: notes = '' notes = notes + \ _('\nSuperceeded (for wage adjustment) by contract: ') + \ wi.contract_id.name vals = {'notes': notes, 'date_end': False} wkf = netsvc.LocalService('workflow') # Set the new contract to the appropriate state wkf.trg_validate(uid, 'hr.contract', c_id, 'signal_confirm', cr) # Terminate the current contract (and trigger appropriate state # change) vals['date_end'] = datetime.strptime( wi.effective_date, '%Y-%m-%d').date() + \ relativedelta(days=-1) hr_obj.write(cr, uid, wi.contract_id.id, vals, context=context) wkf.trg_validate(uid, 'hr.contract', wi.contract_id.id, 'signal_done', cr) return def create(self, cr, uid, vals, context=None): contract_id = vals.get('contract_id', False) if not contract_id: if context is not None: contract_id = context.get('active_id') data = self.pool.get('hr.contract').read(cr, uid, contract_id, ['name', 'date_start'], context=context) # Check that the contract start date is before the effective date if vals['effective_date'] <= data['date_start']: raise models.except_orm( _('Error'), _('The effective date of the adjustment must be after the ' 'contract start date. Contract: %s.') % (data['name'])) wage_incr_ids = self.search( cr, uid, [ ('contract_id', '=', contract_id), ('state', 'in', ['draft', 'confirm', 'approved']), ], context=context) if len(wage_incr_ids) > 0: raise models.except_orm( _('Warning'), _('There is already another wage adjustment in progress for ' 'this contract: %s.') % (data['name'])) return super(wage_increment, self).create(cr, uid, vals, context=context) def do_signal_confirm(self, cr, uid, ids, context=None): for wi in self.browse(cr, uid, ids, context=context): self._check_state(cr, uid, wi, context=context) self.write(cr, uid, wi.id, {'state': 'confirm'}, context=context) def do_signal_approve(self, cr, uid, ids, context=None): for i in ids: self.action_wage_increment(cr, uid, [i], context=context) self.write(cr, uid, i, {'state': 'approve'}, context=context) def unlink(self, cr, uid, ids, context=None): for incr in self.browse(cr, uid, ids, context=context): if incr.state in ['approve']: raise models.except_orm( _('The record cannot be deleted!'), _("""\ You may not delete a record that is in a %s state: Employee: %s""") % (incr.state, incr.employee_id.name)) return super(wage_increment, self).unlink(cr, uid, ids, context=context)
name = fields.Char('Number', required=True, copy=False) ref = fields.Char('Reference', copy=False) period_id = fields.Many2one('account.period', 'Period', required=True, states={'posted =[('readonly',True)]}) journal_id = fields.Many2one('account.journal', 'Journal', required=True, states={'posted =[('readonly',True)]}) state = fields.Selection( [('draft','Unposted'), ('posted','Posted')], 'Status', required=True, readonly=True, copy=False, help='All manually created new journal entries are usually in the status \'Unposted\', ' 'but you can set the option to skip that status on the related journal. ' 'In that case, they will behave as journal entries automatically created by the ' 'system on document validation (invoices, bank statements...) and will be created ' 'in \'Posted\' status.'), line_id = fields.One2many('account.move.line', 'move_id', 'Entries', states={'posted =[('readonly',True)]}, reversal_id = fields.Char('Reversal Entry') to_be_reversed = fields.Boolean('To Be Reversed') to_check = fields.Boolean('To Review', help='Check this box if you are unsure of that journal entry and if you want to note it as \'to be reviewed\' by an accounting expert.'), partner_id = fields.Related('line_id', 'partner_id', type="many2one", relation="res.partner", string="Partner", store={ _name: (lambda self, cr,uid,ids,c: ids, ['line_id'], 10) 'account.move.line = (_get_move_from_lines, ['partner_id'],10) }), amount = fields.Function(_amount_compute, string='Amount', digits_compute=dp.get_precision('Account'), type='float', fnct_search=_search_amount), date = fields.date('Date', required=True, states={'posted =[('readonly',True)]}, select=True), narration =fields.Text('Internal Note'), \ company_id = fields.related('journal_id','company_id',type='many2one',relation='res.company',string='Company', store=True, readonly=True), \ balance = fields.Float('balance', digits_compute=dp.get_precision('Account'), help="This is a field only used for internal purpose and shouldn't be displayed"),
class restday(models.TransientModel): _name = 'hr.restday.wizard' _description = 'Schedule Template Change Wizard' _columns = { 'employee_id': fields.many2one( 'hr.employee', 'Employee', required=True, ), 'contract_id': fields.related( 'employee_id', 'contract_id', type='many2one', relation='hr.contract', string='Contract', readonly=True, ), 'st_current_id': fields.many2one( 'hr.schedule.template', 'Current Template', readonly=True, ), 'st_new_id': fields.many2one( 'hr.schedule.template', 'New Template', ), 'permanent': fields.boolean('Make Permanent', ), 'temp_restday': fields.boolean( 'Temporary Rest Day Change', help="If selected, change the rest day to the specified day only " "for the selected schedule.", ), 'dayofweek': fields.selection( [('0', 'Monday'), ('1', 'Tuesday'), ('2', 'Wednesday'), ('3', 'Thursday'), ('4', 'Friday'), ('5', 'Saturday'), ('6', 'Sunday')], 'Rest Day', select=True, ), 'temp_week_start': fields.date('Start of Week', ), 'week_start': fields.date('Start of Week', ), } _defaults = { 'temp_restday': False, } def onchange_employee(self, cr, uid, ids, ee_id, context=None): res = {'value': {'st_current_id': False}} if ee_id: ee = self.pool.get('hr.employee').browse(cr, uid, ee_id, context=None) res['value'][ 'st_current_id'] = ee.contract_id.schedule_template_id.id return res def onchange_week(self, cr, uid, ids, newdate): res = {'value': {'week_start': newdate}} if newdate: d = datetime.strptime(newdate, "%Y-%m-%d") if d.weekday() != 0: res['value']['week_start'] = False return res return res def onchange_temp_week(self, cr, uid, ids, newdate): res = {'value': {'temp_week_start': newdate}} if newdate: d = datetime.strptime(newdate, "%Y-%m-%d") if d.weekday() != 0: res['value']['temp_week_start'] = False return res return res def _create_detail(self, cr, uid, schedule, actual_dayofweek, template_dayofweek, week_start, context=None): # First, see if there's a schedule for the actual dayofweek. # If so, use it. # for worktime in schedule.template_id.worktime_ids: if worktime.dayofweek == actual_dayofweek: template_dayofweek = actual_dayofweek prevutcdtStart = False prevDayofWeek = False user = self.pool.get('res.users').browse(cr, uid, uid, context=context) local_tz = timezone(user.tz) dSchedStart = datetime.strptime(schedule.date_start, OE_DFORMAT).date() dWeekStart = schedule.date_start < week_start and datetime.strptime( week_start, OE_DFORMAT).date() or dSchedStart for worktime in schedule.template_id.worktime_ids: if worktime.dayofweek != template_dayofweek: continue hour, sep, minute = worktime.hour_from.partition(':') toHour, toSep, toMin = worktime.hour_to.partition(':') if len(sep) == 0 or len(toSep) == 0: raise models.except_orm( _('Invalid Time Format'), _('The time should be entered as HH:MM')) # TODO - Someone affected by DST should fix this # dtStart = datetime.strptime( dWeekStart.strftime('%Y-%m-%d') + ' ' + hour + ':' + minute + ':00', '%Y-%m-%d %H:%M:%S') locldtStart = local_tz.localize(dtStart, is_dst=False) utcdtStart = locldtStart.astimezone(utc) if actual_dayofweek != '0': utcdtStart = utcdtStart + \ relativedelta(days=+int(actual_dayofweek)) dDay = utcdtStart.astimezone(local_tz).date() # If this worktime is a continuation (i.e - after lunch) set the # start time based on the difference from the previous record # if prevDayofWeek and prevDayofWeek == actual_dayofweek: prevHour = prevutcdtStart.strftime('%H') prevMin = prevutcdtStart.strftime('%M') curHour = utcdtStart.strftime('%H') curMin = utcdtStart.strftime('%M') delta_seconds = ( datetime.strptime(curHour + ':' + curMin, '%H:%M') - datetime.strptime(prevHour + ':' + prevMin, '%H:%M')).seconds utcdtStart = prevutcdtStart + timedelta(seconds=+delta_seconds) dDay = prevutcdtStart.astimezone(local_tz).date() delta_seconds = ( datetime.strptime(toHour + ':' + toMin, '%H:%M') - datetime.strptime(hour + ':' + minute, '%H:%M')).seconds utcdtEnd = utcdtStart + timedelta(seconds=+delta_seconds) val = { 'name': schedule.name, 'dayofweek': actual_dayofweek, 'day': dDay, 'date_start': utcdtStart.strftime('%Y-%m-%d %H:%M:%S'), 'date_end': utcdtEnd.strftime('%Y-%m-%d %H:%M:%S'), 'schedule_id': schedule.id, } self.pool.get('hr.schedule').write(cr, uid, schedule.id, { 'detail_ids': [(0, 0, val)], }, context=context) prevDayofWeek = worktime.dayofweek prevutcdtStart = utcdtStart def _change_restday(self, cr, uid, employee_id, week_start, dayofweek, context=None): sched_obj = self.pool.get('hr.schedule') sched_detail_obj = self.pool.get('hr.schedule.detail') schedule_ids = sched_obj.search(cr, uid, [('employee_id', '=', employee_id), ('date_start', '<=', week_start), ('date_end', '>=', week_start), ('state', 'not in', ['locked'])], context=context) sched = sched_obj.browse(cr, uid, schedule_ids[0], context=context) dtFirstDay = datetime.strptime(sched.detail_ids[0].date_start, OE_DTFORMAT) date_start = (dtFirstDay.strftime(OE_DFORMAT) < week_start and week_start + ' ' + dtFirstDay.strftime('%H:%M:%S') or dtFirstDay.strftime(OE_DTFORMAT)) dtNextWeek = datetime.strptime(date_start, OE_DTFORMAT) + relativedelta(weeks=+1) # First get the current rest days rest_days = sched_obj.get_rest_days_by_id( cr, uid, sched.id, dtFirstDay.strftime(OE_DFORMAT), context=context) # Next, remove the schedule detail for the new rest day for dtl in sched.detail_ids: if (dtl.date_start < week_start or datetime.strptime( dtl.date_start, OE_DTFORMAT) >= dtNextWeek): continue if dtl.dayofweek == dayofweek: sched_detail_obj.unlink(cr, uid, dtl.id, context=context) # Enter the new rest day(s) # sched_obj = self.pool.get('hr.schedule') nrest_days = [dayofweek] + rest_days[1:] dSchedStart = datetime.strptime(sched.date_start, OE_DFORMAT).date() dWeekStart = sched.date_start < week_start and datetime.strptime( week_start, OE_DFORMAT).date() or dSchedStart if dWeekStart == dSchedStart: sched_obj.add_restdays(cr, uid, sched, 'restday_ids1', rest_days=nrest_days, context=context) elif dWeekStart == dSchedStart + relativedelta(days=+7): sched_obj.add_restdays(cr, uid, sched, 'restday_ids2', rest_days=nrest_days, context=context) elif dWeekStart == dSchedStart + relativedelta(days=+14): sched_obj.add_restdays(cr, uid, sched, 'restday_ids3', rest_days=nrest_days, context=context) elif dWeekStart == dSchedStart + relativedelta(days=+21): sched_obj.add_restdays(cr, uid, sched, 'restday_ids4', rest_days=nrest_days, context=context) elif dWeekStart == dSchedStart + relativedelta(days=+28): sched_obj.add_restdays(cr, uid, sched, 'restday_ids5', rest_days=nrest_days, context=context) # Last, add a schedule detail for the first rest day in the week using # the template for the new (temp) rest day # if len(rest_days) > 0: self._create_detail(cr, uid, sched, str(rest_days[0]), dayofweek, week_start, context=context) def _remove_add_schedule(self, cr, uid, schedule_id, week_start, tpl_id, context=None): """Remove the current schedule and add a new one in its place according to the new template. If the week that the change starts in is not at the beginning of a schedule create two new schedules to accommodate the truncated old one and the partial new one. """ sched_obj = self.pool.get('hr.schedule') sched = sched_obj.browse(cr, uid, schedule_id, context=context) vals2 = False vals1 = { 'name': sched.name, 'employee_id': sched.employee_id.id, 'template_id': tpl_id, 'date_start': sched.date_start, 'date_end': sched.date_end, } if week_start > sched.date_start: dWeekStart = datetime.strptime(week_start, '%Y-%m-%d').date() start_day = dWeekStart.strftime('%Y-%m-%d') vals1['template_id'] = sched.template_id.id vals1['date_end'] = (dWeekStart + relativedelta(days=-1)).strftime('%Y-%m-%d') vals2 = { 'name': (sched.employee_id.name + ': ' + start_day + ' Wk ' + str(dWeekStart.isocalendar()[1])), 'employee_id': sched.employee_id.id, 'template_id': tpl_id, 'date_start': start_day, 'date_end': sched.date_end, } sched_obj.unlink(cr, uid, schedule_id, context=context) _l.warning('vals1: %s', vals1) sched_obj.create(cr, uid, vals1, context=context) if vals2: _l.warning('vals2: %s', vals2) sched_obj.create(cr, uid, vals2, context=context) def _change_by_template(self, cr, uid, employee_id, week_start, new_template_id, doall, context=None): sched_obj = self.pool.get('hr.schedule') schedule_ids = sched_obj.search(cr, uid, [('employee_id', '=', employee_id), ('date_start', '<=', week_start), ('date_end', '>=', week_start), ('state', 'not in', ['locked'])], context=context) # Remove the current schedule and add a new one in its place according # to the new template # if len(schedule_ids) > 0: self._remove_add_schedule(cr, uid, schedule_ids[0], week_start, new_template_id, context=context) # Also, change all subsequent schedules if so directed if doall: ids = sched_obj.search(cr, uid, [('employee_id', '=', employee_id), ('date_start', '>', week_start), ('state', 'not in', ['locked'])], context=context) for i in ids: self._remove_add_schedule(cr, uid, i, week_start, new_template_id, context) def change_restday(self, cr, uid, ids, context=None): data = self.read(cr, uid, ids[0], [], context=context) # Change the rest day for only one schedule if (data.get('temp_restday') and data.get('dayofweek') and data.get('temp_week_start')): self._change_restday(cr, uid, data['employee_id'][0], data['temp_week_start'], data['dayofweek'], context=context) # Change entire week's schedule to the chosen schedule template if (not data.get('temp_restday') and data.get('st_new_id') and data.get('week_start')): if data.get('week_start', False): self._change_by_template(cr, uid, data['employee_id'][0], data['week_start'], data['st_new_id'][0], data.get('permanent', False), context=context) # If this change is permanent modify employee's contract to # reflect the new template # if data.get('permanent', False): self.pool.get('hr.contract').write( cr, uid, data['contract_id'][0], { 'schedule_template_id': data['st_new_id'][0], }, context=context) return { 'name': 'Change Schedule Template', 'view_type': 'form', 'view_mode': 'form', 'res_model': 'hr.restday.wizard', 'type': 'ir.actions.act_window', 'target': 'new', 'context': context }
class account_move_line(osv.osv): _inherit = "account.move.line" @api.one @api.depends('credit', 'debit', 'tax_code_id') def _compute_tax_base_values_for_manual_journal_items(self): if self.tax_code_id: if self.tax_code_id.code in ('1', '6', '8'): self.mtd_tax_amount = (self.credit - self.debit) elif self.tax_code_id.code in ('2', '9', '7'): self.mtd_tax_amount = (self.debit - self.credit) elif self.tax_code_id.code == '4': self.mtd_tax_amount = (self.debit - self.credit) journal_entry_obj = self.env['account.move.line'].search([ ('move_id', '=', self.move_id.id) ]) if journal_entry_obj: for line in journal_entry_obj: if line.tax_code_id.code == '2': self.mtd_tax_amount = (self.credit - self.debit) else: self.mtd_tax_amount = 0.00 _columns = { 'vat': fields.boolean(string="VAT Posted", default=False, readonly=True), 'vat_submission_id': fields.many2one('mtd_vat.vat_submission_logs', string='VAT Submission Period'), 'unique_number': fields.related('vat_submission_id', 'unique_number', type='char', string="HMRC Unique Number", readonly=True), 'mtd_tax_amount': fields.float( 'Mtd Tax/Base Amount', compute="_compute_tax_base_values_for_manual_journal_items", digits=dp.get_precision('Account'), store=True) } # Override of the base function reconcile , removing the control for the account if is field reconciled checked or not def mtd_reconcile(self, cr, uid, ids, type='auto', writeoff_acc_id=False, writeoff_period_id=False, writeoff_journal_id=False, context=None): account_obj = self.pool.get('account.account') move_obj = self.pool.get('account.move') move_rec_obj = self.pool.get('account.move.reconcile') partner_obj = self.pool.get('res.partner') currency_obj = self.pool.get('res.currency') lines = self.browse(cr, uid, ids, context=context) unrec_lines = filter(lambda x: not x['reconcile_id'], lines) credit = debit = 0.0 currency = 0.0 account_id = False partner_id = False if context is None: context = {} company_list = [] for line in lines: if company_list and not line.company_id.id in company_list: raise osv.except_osv( _('Warning!'), _('To reconcile the entries company should be the same for all entries.' )) company_list.append(line.company_id.id) for line in unrec_lines: if line.state != 'valid': raise osv.except_osv( _('Error!'), _('Entry "%s" is not valid !') % line.name) credit += line['credit'] debit += line['debit'] currency += line['amount_currency'] or 0.0 account_id = line['account_id']['id'] partner_id = (line['partner_id'] and line['partner_id']['id']) or False writeoff = debit - credit # Ifdate_p in context => take this date if context.has_key('date_p') and context['date_p']: date = context['date_p'] else: date = time.strftime('%Y-%m-%d') cr.execute('SELECT account_id, reconcile_id '\ 'FROM account_move_line '\ 'WHERE id IN %s '\ 'GROUP BY account_id,reconcile_id', (tuple(ids), )) r = cr.fetchall() #TODO: move this check to a constraint in the account_move_reconcile object if len(r) != 1: raise osv.except_osv( _('Error'), _('Entries are not of the same account or already reconciled ! ' )) if not unrec_lines: raise osv.except_osv(_('Error!'), _('Entry is already reconciled.')) account = account_obj.browse(cr, uid, account_id, context=context) if r[0][1] != None: raise osv.except_osv(_('Error!'), _('Some entries are already reconciled.')) if (not currency_obj.is_zero(cr, uid, account.company_id.currency_id, writeoff)) or \ (account.currency_id and (not currency_obj.is_zero(cr, uid, account.currency_id, currency))): # DO NOT FORWARD PORT if not writeoff_acc_id: if writeoff > 0: writeoff_acc_id = account.company_id.expense_currency_exchange_account_id.id else: writeoff_acc_id = account.company_id.income_currency_exchange_account_id.id if not writeoff_acc_id: raise osv.except_osv( _('Warning!'), _('You have to provide an account for the write off/exchange difference entry.' )) if writeoff > 0: debit = writeoff credit = 0.0 self_credit = writeoff self_debit = 0.0 else: debit = 0.0 credit = -writeoff self_credit = 0.0 self_debit = -writeoff # If comment exist in context, take it if 'comment' in context and context['comment']: libelle = context['comment'] else: libelle = _('Write-Off') cur_obj = self.pool.get('res.currency') cur_id = False amount_currency_writeoff = 0.0 if context.get('company_currency_id', False) != context.get( 'currency_id', False): cur_id = context.get('currency_id', False) for line in unrec_lines: if line.currency_id and line.currency_id.id == context.get( 'currency_id', False): amount_currency_writeoff += line.amount_currency else: tmp_amount = cur_obj.compute( cr, uid, line.account_id.company_id.currency_id.id, context.get('currency_id', False), abs(line.debit - line.credit), context={'date': line.date}) amount_currency_writeoff += ( line.debit > 0) and tmp_amount or -tmp_amount writeoff_lines = [ (0, 0, { 'name': libelle, 'debit': self_debit, 'credit': self_credit, 'account_id': account_id, 'date': date, 'partner_id': partner_id, 'currency_id': cur_id or (account.currency_id.id or False), 'amount_currency': amount_currency_writeoff and -1 * amount_currency_writeoff or (account.currency_id.id and -1 * currency or 0.0) }), (0, 0, { 'name': libelle, 'debit': debit, 'credit': credit, 'account_id': writeoff_acc_id, 'analytic_account_id': context.get('analytic_id', False), 'date': date, 'partner_id': partner_id, 'currency_id': cur_id or (account.currency_id.id or False), 'amount_currency': amount_currency_writeoff and amount_currency_writeoff or (account.currency_id.id and currency or 0.0) }) ] # DO NOT FORWARD PORT # In some exceptional situations (partial payment from a bank statement in foreign # currency), a write-off can be introduced at the very last moment due to currency # conversion. We record it on the bank statement account move. if context.get('bs_move_id'): writeoff_move_id = context['bs_move_id'] for l in writeoff_lines: self.create(cr, uid, dict(l[2], move_id=writeoff_move_id), dict(context, novalidate=True)) if not move_obj.validate( cr, uid, writeoff_move_id, context=context): raise osv.except_osv( _('Error!'), _('You cannot validate a non-balanced entry.')) else: writeoff_move_id = move_obj.create( cr, uid, { 'period_id': writeoff_period_id, 'journal_id': writeoff_journal_id, 'date': date, 'state': 'draft', 'line_id': writeoff_lines }) writeoff_line_ids = self.search( cr, uid, [('move_id', '=', writeoff_move_id), ('account_id', '=', account_id)]) if account_id == writeoff_acc_id: writeoff_line_ids = [writeoff_line_ids[1]] ids += writeoff_line_ids # marking the lines as reconciled does not change their validity, so there is no need # to revalidate their moves completely. reconcile_context = dict(context, novalidate=True) r_id = move_rec_obj.create(cr, uid, {'type': type}, context=reconcile_context) self.write(cr, uid, ids, { 'reconcile_id': r_id, 'reconcile_partial_id': False }, context=reconcile_context) # the id of the move.reconcile is written in the move.line (self) by the create method above # because of the way the line_id are defined: (4, x, False) for id in ids: workflow.trg_trigger(uid, 'account.move.line', id, cr) if lines and lines[0]: partner_id = lines[0].partner_id and lines[0].partner_id.id or False if partner_id and not partner_obj.has_something_to_reconcile( cr, uid, partner_id, context=context): partner_obj.mark_as_reconciled(cr, uid, [partner_id], context=context) return r_id