def check_wh_lines_fortnights(self): """ Check that every wh iva line belongs to the wh iva fortnight.""" period = self.env['account.period'] error_msg = str() fortnight_str = {'True': ' - Second Fortnight)', 'False': ' - First Fortnight)'} for awi_brw in self: if awi_brw.type in ['out_invoice']: return True for awil_brw in awi_brw.wh_lines: awil_period_id, awil_fortnight = period.find_fortnight( awil_brw.invoice_id.date_invoice) if awil_period_id != awi_brw.period_id.id or \ awil_fortnight != awi_brw.fortnight: error_msg += \ (" * Line '" + awil_brw.invoice_id.number + "' belongs to (" + period.browse(awil_period_id).name + fortnight_str[awil_fortnight] + ".\n") if error_msg: raise exceptions.except_orm( _("Invalid action !"), _("Some withholding lines being withheld dont match" " with the withholding document period and" " fortnight.\n\n * Withholding VAT document correspond" " to (" + awi_brw.period_id.name + fortnight_str[ awi_brw.fortnight] + ".\n\n" + error_msg)) else: return True
def get_devotee_list(self,cr,uid,ids,context=None): res={} report_ids=[] data=self.browse(cr,uid,ids) from_date=data[0].from_date to_date=data[0].to_date print from_date print to_date devotee_obj=self.pool.get('jkp.devotees') categ_id =self.pool.get('jkp.category').search(cr,uid,( [('name','=','Prominent')] )) print "category ids ids......................",categ_id if to_date and from_date: report_ids=devotee_obj.search(cr,uid,[('today_date','>=' ,from_date),('today_date','<=' ,to_date),('category_ids','in',categ_id)]) else: report_ids=devotee_obj.search(cr,uid,[('category_ids','in',categ_id)]) print "report Ids are ",report_ids self.write(cr,uid,ids,{'devotee_details':[(6,0,report_ids)]}) report_obj = self.pool.get('ir.actions.report.xml') datas = {'ids' : ids} rpt_id = report_obj.search(cr, uid, [('report_name','=','prominent.devotees')])[0] if not rpt_id: raise osv.except_osv(_('Invalid action !'), _('Report for this name does not exists.')) rpt_type = report_obj.read(cr, uid, rpt_id, ['report_name']) return { 'type' : 'ir.actions.report.xml', 'report_name':str(rpt_type['report_name']), 'datas' : datas, 'nodestroy':True, } return True
def create(self, vals): # Move request for move_requ in self: if vals['type'] == 'move': # Check if this employee is working this day if (move_requ._check_is_working( vals['employee_id'], vals['old_date'])): return super(hr_planning_day_move_request, self).create(vals) # Check if the move will have no effect elif vals['old_date'] == vals['new_date']: raise exceptions.Warning(_('Warning'), _(u'You chose the same date')) else: employee_name = self.env['hr.employee'].browse( vals['employee_id']).name raise exceptions.Warning( _('Warning'), _(u'{} does not work this day : {}').format( employee_name, vals['old_date']) ) # Add request else: vals['old_date'] = False return super(hr_planning_day_move_request, self).create(vals)
def run_manually_old(self, cr, uid, ids, context=None): if uid != SUPERUSER_ID: raise exceptions.AccessError(_("Only the admin user is allowed to execute inactive cron jobs manually")) wizard = self.browse(cr, uid, ids[0], context=context) try: cr.execute( """SELECT * FROM ir_cron WHERE id=%s FOR UPDATE NOWAIT""", (ids[0],), ) except OperationalError as e: if getattr(e, "pgcode", None) == "55P03": raise exceptions.Warning(_("Another process/thread is already busy executing this job")) raise _logger.info("Job `%s` triggered from form", wizard.name) ctx = context.copy() ctx.pop("active_test", None) method = getattr(self.pool.get(wizard.model), wizard.function) args = safe_eval("tuple(%s)" % (wizard.args or "")) return method(cr, uid, *args)
def _get_counterpart_move_line_vals(self, invoice=False): if self.payment_type == 'transfer': name = self.name else: name = '' if self.partner_type == 'customer': if self.payment_type == 'inbound': name += _("Customer Payment") elif self.payment_type == 'outbound': name += _("Customer Refund") elif self.partner_type == 'supplier': if self.payment_type == 'inbound': name += _("Vendor Refund") elif self.payment_type == 'outbound': name += _("Vendor Payment") if invoice: name += ': ' for inv in invoice: if inv.move_id: name += inv.number + ', ' name = name[:len(name)-2] return { 'name': name, 'account_id': self.destination_account_id.id, 'journal_id': self.journal_id.id, 'currency_id': self.currency_id != self.company_id.currency_id and self.currency_id.id or False, 'payment_id': self.id, }
def account_move_get(self, register_id): ''' This method prepare the creation of the account move related to the given register. :param register_id: Id of voucher for which we are creating account_move. :return: mapping between fieldname and value of account move to create :rtype: dict ''' seq_obj = self.env['ir.sequence'] register_brw = self.env['payment.register'].browse(register_id) if register_brw.number: name = register_brw.number elif register_brw.journal_id.sequence_id: if not register_brw.journal_id.sequence_id.active: raise Warning(_('Configuration Error !'), _('Please activate the sequence of selected journal !')) name = seq_obj.next_by_id(register_brw.journal_id.sequence_id.id) else: raise Warning(_('Error!'), _('Please define a sequence on the journal.')) if not register_brw.reference: ref = name.replace('/', '') else: ref = register_brw.reference move = { 'name': name, 'journal_id': register_brw.journal_id.id, 'narration': register_brw.narration, 'date': register_brw.date, 'ref': ref, 'period_id': register_brw.period_id and register_brw.period_id.id or False } return move # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
def unlink(self): for asset in self: if asset.state in ['open', 'close']: raise UserError(_('You cannot delete a document is in %s state.') % (asset.state,)) if asset.account_move_ids: raise UserError(_('You cannot delete a document that contains posted entries.')) return super(AccountAssetAsset, self).unlink()
def run(self, Ymk_id, force=False): """ Run the synchronization :param Ymk_id: identifier of the record on YmkCommerce """ self.Ymk_id = Ymk_id try: self.Ymk_record = self._get_Ymk_data() except IDMissingInBackend: return _('Record does no longer exist in YmkCommerce') skip = self._must_skip() if skip: return skip binding = self._get_binding() if not force and self._is_uptodate(binding): return _('Already up-to-date.') self._before_import() # import the missing linked resources self._import_dependencies() map_record = self._map_data() if binding: record = self._update_data(map_record) self._update(binding, record) else: record = self._create_data(map_record) binding = self._create(record) self.binder.bind(self.Ymk_id, binding) self._after_import(binding)
def gainloss_move_line_create(self, register, move_id): company = register.company_id ctx = dict(self._context) ctx.update({'date': register.date}) amount_payin_company_currency = self.with_context(ctx)._convert_amount(register.amount_payin, register.id) # make the rounding as defined in company currency. amount_payin_company_currency = company.currency_id.round(amount_payin_company_currency) paid_amount_in_company_currency = company.currency_id.round(register.paid_amount_in_company_currency) writeoff_amount_local = company.currency_id.round(register.writeoff_amount_local) # amount to post amount = amount_payin_company_currency - paid_amount_in_company_currency + writeoff_amount_local if abs(amount) < 10 ** -4: return False if not company.income_currency_exchange_account_id or not company.expense_currency_exchange_account_id: raise Warning(_('Accounting Error !'), _('Gain/Loss Exchange Rate Account is not setup properly! Please see Settings > Configuration > Accounting.')) move_line = { 'journal_id': register.journal_id.id, 'period_id': register.period_id.id, 'name': register.name or '/', 'account_id': amount > 0 and company.income_currency_exchange_account_id.id or company.expense_currency_exchange_account_id.id, 'move_id': move_id.id, 'partner_id': register.partner_id.id, 'currency_id': False, # 'analytic_account_id': register_brw.account_analytic_id and register_brw.account_analytic_id.id or False, 'amount_currency': 0.0, 'quantity': 1, 'credit': amount > 0 and amount or 0.0, 'debit': amount < 0 and -amount or 0.0, 'date': register.date } move_line_id = self.env['account.move.line'].create(move_line) # Assign amount to gainloss_amount field register.write({'gainloss_amount': amount}) return move_line_id
def create_production_planning_order(self): if not self.bom_ids: raise Warning(_('This product has no associated bill of materials')) if not self.routing_ids: raise Warning(_('This product has no associated production line')) order = self.env['production.planning'].orders.create({ 'product_id': self.id, 'bom_id': self.bom_ids[0].id, 'line_id': self.routing_ids[0].id }) view_id = self.env.ref( 'stock_available_ph.production_planning_new_order_form') return { 'type': 'ir.actions.act_window', 'view_type': 'form', 'view_mode': 'form', 'view_id': view_id.id, 'res_model': 'production.planning.orders', 'res_id': order.id, 'target': 'new', 'context': self.env.context, }
def _balance_check(self): for stmt in self: if not stmt.currency_id.is_zero(stmt.difference): if stmt.journal_type == 'cash': if stmt.difference < 0.0: account = stmt.journal_id.loss_account_id name = _('Loss') else: # statement.difference > 0.0 account = stmt.journal_id.profit_account_id name = _('Profit') if not account: raise UserError(_('There is no account defined on the journal %s for %s involved in a cash difference.') % (stmt.journal_id.name, name)) values = { 'statement_id': stmt.id, 'account_id': account.id, 'amount': stmt.difference, 'name': _("Cash difference observed during the counting (%s)") % name, } self.env['account.bank.statement.line'].create(values) else: balance_end_real = formatLang(self.env, stmt.balance_end_real, currency_obj=stmt.currency_id) balance_end = formatLang(self.env, stmt.balance_end, currency_obj=stmt.currency_id) raise UserError(_('The ending balance is incorrect !\nThe expected balance (%s) is different from the computed one. (%s)') % (balance_end_real, balance_end)) return True
def create(self, vals): if not (vals['name'] and vals['supplier_id']): # raise osv.except_osv(_("Error"), _("Please provide proper # Information")) raise Warning(_("Error ! Please provide proper Information")) # search for books of these editor not already linked with this # supplier : select = """select product_tmpl_id\n"""\ """from product_product\n"""\ """where editor = %s\n"""\ """ and id not in (select product_tmpl_id from product_supplierinfo" "where name = %s)""" % (vals['name'], vals['supplier_id']) self._cr.execute(select) if not self._cr.rowcount: raise Warning(_("Error ! No book to apply this relation")) sup_info = self.env['product.supplierinfo'] last_id = 0 for book_id in self._cr.fetchall(): params = { 'name': vals['supplier_id'], # 'product_id': book_id[0], 'product_tmpl_id': book_id[0], 'sequence': vals['sequence'], 'delay': vals['delay'], 'min_qty': vals['min_qty'], } tmp_id = sup_info.create(params) last_id = last_id < tmp_id.id and last_id or tmp_id.id return last_id
def write(self, vals): for journal in self: if ('company_id' in vals and journal.company_id.id != vals['company_id']): if self.env['account.move'].search([('journal_id', 'in', self.ids)], limit=1): raise UserError(_('This journal already contains items, therefore you cannot modify its company.')) if ('code' in vals and journal.code != vals['code']): if self.env['account.move'].search([('journal_id', 'in', self.ids)], limit=1): raise UserError(_('This journal already contains items, therefore you cannot modify its short name.')) new_prefix = self._get_sequence_prefix(vals['code'], refund=False) journal.sequence_id.write({'prefix': new_prefix}) if journal.refund_sequence_id: new_prefix = self._get_sequence_prefix(vals['code'], refund=True) journal.refund_sequence_id.write({'prefix': new_prefix}) if 'currency_id' in vals: if not 'default_debit_account_id' in vals and self.default_debit_account_id: self.default_debit_account_id.currency_id = vals['currency_id'] if not 'default_credit_account_id' in vals and self.default_credit_account_id: self.default_credit_account_id.currency_id = vals['currency_id'] result = super(AccountJournal, self).write(vals) # Create the bank_account_id if necessary if 'bank_acc_number' in vals: for journal in self.filtered(lambda r: r.type == 'bank' and not r.bank_account_id): journal.set_bank_account(vals.get('bank_acc_number'), vals.get('bank_id')) return result
def action_invoice_create(self, grouped=False, final=False): """ Create the invoice associated to the SO. :param grouped: if True, invoices are grouped by SO id. If False, invoices are grouped by (partner_invoice_id, currency) :param final: if True, refunds will be generated if necessary :returns: list of created invoices """ inv_obj = self.env['account.invoice'] precision = self.env['decimal.precision'].precision_get('Product Unit of Measure') invoices = {} references = {} for order in self: group_key = order.id if grouped else (order.partner_invoice_id.id, order.currency_id.id) for line in order.order_line.sorted(key=lambda l: l.qty_to_invoice < 0): if float_is_zero(line.qty_to_invoice, precision_digits=precision): continue if group_key not in invoices: inv_data = order._prepare_invoice() invoice = inv_obj.create(inv_data) references[invoice] = order invoices[group_key] = invoice elif group_key in invoices: vals = {} if order.name not in invoices[group_key].origin.split(', '): vals['origin'] = invoices[group_key].origin + ', ' + order.name if order.client_order_ref and order.client_order_ref not in invoices[group_key].name.split(', '): vals['name'] = invoices[group_key].name + ', ' + order.client_order_ref invoices[group_key].write(vals) if line.qty_to_invoice > 0: line.invoice_line_create(invoices[group_key].id, line.qty_to_invoice) elif line.qty_to_invoice < 0 and final: line.invoice_line_create(invoices[group_key].id, line.qty_to_invoice) if references.get(invoices.get(group_key)): if order not in references[invoices[group_key]]: references[invoice] = references[invoice] | order if not invoices: raise UserError(_('There is no invoicable line.')) for invoice in invoices.values(): if not invoice.invoice_line_ids: raise UserError(_('There is no invoicable line.')) # If invoice is negative, do a refund invoice instead if invoice.amount_untaxed < 0: invoice.type = 'out_refund' for line in invoice.invoice_line_ids: line.quantity = -line.quantity # Use additional field helper function (for account extensions) for line in invoice.invoice_line_ids: line._set_additional_fields(invoice) # Necessary to force computation of taxes. In account_invoice, they are triggered # by onchanges, which are not triggered when doing a create. invoice.compute_taxes() invoice.message_post_with_view('mail.message_origin_link', values={'self': invoice, 'origin': references[invoice]}, subtype_id=self.env.ref('mail.mt_note').id) return [inv.id for inv in invoices.values()]
def write(self, vals): res = {} update_sequence = "update product_supplierinfo set sequence = %s"\ "where name = %s" update_delay = "update product_supplierinfo set delay = %s"\ "where name = %s" # relations = self.browse(cr, user, ids) # for rel, idn in zip(relations, ids): for rel, idn in zip(self, self.ids): # cannot change supplier here. Must create a new relation: original_supplier_id = rel.supplier_id.id if not original_supplier_id: raise Warning(_("Warning ! Cannot set supplier in this form." "Please create a new relation.")) new_supplier_id = vals.get('supplier_id', 0) supplier_change = new_supplier_id != 0 and (idn < 0 or (original_supplier_id != new_supplier_id)) if supplier_change: raise Warning(_("Warning ! Cannot set supplier in this form." "Please create a new relation.")) else: if 'sequence' in vals: params = [vals.get('sequence', 0), original_supplier_id] self._cr.execute(update_sequence, params) if 'delay' in vals: params = [vals.get('delay', 0), original_supplier_id] self._cr.execute(update_delay, params) res[str(idn)] = {} return res
def onchange_complete(self): message = False gtin14_id = self.product_id.\ gtin14_partner_specific(self.transfer_id.picking_id.partner_id) if \ self.transfer_id else False complete_qty = gtin14_id.units if gtin14_id else \ self.product_id.box_elements if complete_qty > 0: required_qty = self.complete * complete_qty if required_qty > self.quantity: self.complete = 0 self.rest = self.quantity message = _('Insufficient quantity to satisfy the required complete units!') else: self.complete = self.complete self.rest = self.quantity - required_qty else: self.complete = 0 message = _('Complete qty is not defined for this product!') res = {} if message: res['warning'] = {'title': _('Warning'), 'message': message} return res
def default_get(self, fields): request_line_obj = self.env['purchase.request.line'] request_line_ids = self._context.get('active_ids', []) active_model = self.env.context['active_model'] res = super(PurchaseRequestLineMakePurchaseRequisition, self).default_get(fields) if not request_line_ids: return res assert active_model == 'purchase.request.line', \ 'Bad context propagation' items = [] for line in request_line_obj.browse(request_line_ids): items.append([0, 0, self._prepare_item(line)]) res['item_ids'] = items operating_unit_id = False for line in request_line_obj.browse(request_line_ids): line_operating_unit_id = line.request_id.operating_unit_id \ and line.request_id.operating_unit_id.id or False if operating_unit_id is not False \ and line_operating_unit_id != operating_unit_id \ and not line.request_id.is_central_purchase: raise except_orm( _('Could not process !'), _('You have to select lines ' 'from the same operating unit.')) else: operating_unit_id = line_operating_unit_id res['operating_unit_id'] = operating_unit_id return res
def action_signature(self): """Write hash and system_entry_date """ # duvida: usar esta accao ou adicionar action_sign a incluir num workflow redesenhado, que substitua o original ???? for invoice in self: # if invoice.state in ('open', 'paid', 'cancel') # not necessary, wkf determines properlly when this action is called # continues when it is not necessary to sign the invoices if (invoice.type in ('out_refund','out_invoice') and invoice.journal_id.self_billing) or (invoice.type in ('in_refund','in_invoice') and not invoice.journal_id.self_billing ) : continue inv_date = str(invoice.date_invoice) now = invoice.system_entry_date or datetime.datetime.now() try: invoiceNo = str(invoice.journal_id.saft_inv_type+' '+invoice.number) except TypeError: raise osv.except_osv(_('Error !'), _("Please set the doc type at Journal's SAFT parameters!")) return gross_total = self.grosstotal(invoice.id) prev_hash = self.get_hash(invoice.id) message = inv_date + ';' + str(now)[:19].replace(' ', 'T') + ';' + invoiceNo + ';' + gross_total + ';' + prev_hash signature = os.popen('echo -n "' + message + '" | openssl dgst -sha1 -sign ' + priv_key + ' | openssl enc -base64 -A', "r").read() self._cr.execute("UPDATE account_invoice SET hash = '%s' WHERE id = %d" % (signature, invoice.id)) if not invoice.system_entry_date: self._cr.execute("UPDATE account_invoice SET system_entry_date = '%s' WHERE id = %d" %(now, invoice.id) ) return True
def _check_code(self): try: l = eval(self.code) if not isinstance(l, types.LambdaType): raise ValueError(_("The python code must be a lambda.")) except (SyntaxError, NameError, ): raise ValueError(_("The python code must be a lambda."))
def club_student(self, cr, uid, ids, context=None): if not ids: return [] pos_line_obj = self.pool.get('pos.order.line') inv = self.browse(cr, uid, ids[0], context=context) registration_id = pos_line_obj.search(cr, uid, [ ('student_id', '=', inv.id), ('type', '=', 'registration'), ('academic_year_id', '=', inv.academic_year_id.id), ('qty', '!=', -1), ('refunded', '=', False)]) registration = pos_line_obj.browse(cr, uid, registration_id) if not registration.order_id or (registration.order_id and registration.order_id.state == 'draft'): raise osv.except_osv(_('Warning!'), _('There is no registration paid for this academic year: %s.') % inv.academic_year_id.name) dummy, view_id = self.pool.get('ir.model.data').get_object_reference(cr, uid, 'oschool', 'view_oschool_club_generate') return { 'name': _("Generate Club"), 'view_mode': 'form', 'view_id': view_id, 'view_type': 'form', 'res_model': 'oschool.club.generate', 'type': 'ir.actions.act_window', 'nodestroy': True, 'target': 'new', 'domain': '[]', 'context': { 'academic_year_id': inv.academic_year_id.id, } }
def action_cancel(self, *args): account_move_obj = self.pool.get('account.move') invoices = self.browse(self.ids) # Sysop - unkown i - quick fix. Todo: find what it means i=1 for invoice in invoices: if invoice.move_id.id: # invoices that are signed can not be deleted if (invoice.type in ('out_refund','out_invoice') and not invoice.journal_id.self_billing) or (invoice.type in ('in_refund','in_invoice') and invoice.journal_id.self_billing ): raise osv.except_osv(_('Error !'), _('You cannot cancel confirmed Invoices subject to digital signature!')) return False account_move_obj.button_cancel([invoice.move_id.id]) # delete the move this invoice was pointing to # Note that the corresponding move_lines and move_reconciles # will be automatically deleted too account_move_obj.unlink([i['move_id'][0]]) if invoice.payment_ids: account_move_line_obj = self.pool.get('account.move.line') pay_ids = account_move_line_obj.browse(i['payment_ids']) for move_line in pay_ids: if move_line.reconcile_partial_id and move_line.reconcile_partial_id.line_partial_ids: raise osv.except_osv(_('Error !'), _('You cannot cancel the Invoice which is Partially Paid! You need to unreconcile concerned payment entries!')) self.write(self.ids, {'state':'cancel', 'move_id':False}) self._log_event(self.ids, -1.0, 'Cancel Invoice') return True
def create(self, vals): if 'content' in vals and vals.get('forum_id'): vals['content'] = self._update_content(vals['content'], vals['forum_id']) post = super(Post, self.with_context(mail_create_nolog=True)).create(vals) # deleted or closed questions if post.parent_id and (post.parent_id.state == 'close' or post.parent_id.active is False): raise UserError(_('Posting answer on a [Deleted] or [Closed] question is not possible')) # karma-based access if not post.parent_id and not post.can_ask: raise KarmaError('Not enough karma to create a new question') elif post.parent_id and not post.can_answer: raise KarmaError('Not enough karma to answer to a question') # messaging and chatter base_url = self.env['ir.config_parameter'].get_param('web.base.url') if post.parent_id: body = _( '<p>A new answer for <i>%s</i> has been posted. <a href="%s/forum/%s/question/%s">Click here to access the post.</a></p>' % (post.parent_id.name, base_url, slug(post.parent_id.forum_id), slug(post.parent_id)) ) post.parent_id.message_post(subject=_('Re: %s') % post.parent_id.name, body=body, subtype='website_forum.mt_answer_new') else: body = _( '<p>A new question <i>%s</i> has been asked on %s. <a href="%s/forum/%s/question/%s">Click here to access the question.</a></p>' % (post.name, post.forum_id.name, base_url, slug(post.forum_id), slug(post)) ) post.message_post(subject=post.name, body=body, subtype='website_forum.mt_question_new') self.env.user.sudo().add_karma(post.forum_id.karma_gen_question_new) return post
def _check_line_dimension(self, inf): # For account non asset/liability line must have section/project for line in inf.line_ids: report_type = line.account_id.user_type.report_type if report_type not in ('asset', 'liability'): if not line.section_id and not line.project_id: raise ValidationError( _('%s is non-banlance sheet item, it requires ' 'Section/Project') % (line.account_id.code,)) if not line.activity_id or not line.activity_group_id: raise ValidationError( _('%s is non-banlance sheet item, it requires ' 'Activity Group and Activity') % (line.account_id.code,)) else: if line.section_id or line.project_id: raise ValidationError( _('%s is banlance sheet item, it do not require AG/A ' 'or Section/Project') % (line.account_id.code,)) for line in inf.line_ids: if line.activity_id and \ line.activity_id.account_id != line.account_id: raise ValidationError( _('%s does not belong to activity %s') % (line.account_id.code, line.activity_id.name))
def open_map(self): self.ensure_one() map_website = self.env.user.context_map_website_id if not map_website: raise UserError( _('Missing map provider: ' 'you should set it in your preferences.')) if (map_website.lat_lon_url and hasattr(self, 'partner_latitude') and self.partner_latitude and self.partner_longitude): url = self._prepare_url( map_website.lat_lon_url, { '{LATITUDE}': self.partner_latitude, '{LONGITUDE}': self.partner_longitude}) else: if not map_website.address_url: raise UserError( _("Missing parameter 'URL that uses the address' " "for map website '%s'.") % map_website.name) url = self._prepare_url( map_website.address_url, {'{ADDRESS}': self._address_as_string()}) return { 'type': 'ir.actions.act_url', 'url': url, 'target': 'new', }
def _check_tax_line(self, inf): journal_type = inf.journal_id.type tax_lines = inf.line_ids.filtered('tax_id') for line in tax_lines: if line.tax_id.account_collected_id != line.account_id: raise ValidationError( _("Invaid Tax Account Code\n%s's account code should be " "%s") % (line.tax_id.account_collected_id.code, line.account_id.code)) if not line.taxbranch_id: raise ValidationError(_('No tax branch for tax line')) if not line.tax_invoice_number: raise ValidationError(_('No tax invoice number for tax line')) if (line.debit or line.credit) and not line.tax_base_amount: raise ValidationError(_('Tax Base should not be zero!')) # Sales, tax must be in credit and debit for refund # Purchase, tax must be in debit and redit for refund invalid = False if journal_type in SALE_JOURNAL: if journal_type != 'sale_refund': invalid = line.debit > 0 else: invalid = line.credit > 0 if journal_type in PURCHASE_JOURNAL: if journal_type != 'purchase_refund': invalid = line.credit > 0 else: invalid = line.debit > 0 if invalid: raise ValidationError( _('Tax in wrong side of dr/cr as refer to journal type!'))
def validate_start(self): if not self.contacts: raise ValidationError( _('You have nobody to dial. Add contacts first :-)')) elif self.dialer_type == 'stasis' and not self.sound_file: raise ValidationError( _('Dialer type is Stasis and Sound File not set!')) elif self.dialer_type == 'dialplan' and not self.context_name: raise ValidationError( _('Dialer type is Dialplan and Asterisk context not set!')) # Check routing invalid_destinations = [] for dst in xrange(0, 10): self.env.cr.execute("""SELECT peer FROM asterisk_dialer_route WHERE dialer=%s AND '%s%s' like CONCAT(pattern,'%%') """ % (self.id, dst, dst) ) peers = self.env.cr.dictfetchall() if not peers: invalid_destinations.append(str(dst)) if invalid_destinations: raise ValidationError( _("No routes for destinations: %s") % ', '.join( invalid_destinations))
def write(self, cr, uid, ids, vals, context=None): if 'name' in vals: if vals['name'].startswith('-'): raise osv.except_osv(_('Error'), _('The name of the group can not start with "-"')) res = super(Groups, self).write(cr, uid, ids, vals, context=context) return res
def onchange_address_home_id(self): if self.address_home_id and self.address_id and \ self.address_home_id != self.address_id: raise Warning(_('Configuration Error!'), _( 'Home Address and working address should be same!')) if self.address_home_id: self.address_home_id.write({'supplier': True, 'employee': True})
def run_manually(self): """Run a job from the cron form view.""" if self.env.uid != SUPERUSER_ID and (not self.active or not self.numbercall): raise exceptions.AccessError(_("Only the admin user is allowed to " "execute inactive cron jobs manually")) try: # Try to grab an exclusive lock on the job row # until the end of the transaction self.env.cr.execute( """SELECT * FROM ir_cron WHERE id=%s FOR UPDATE NOWAIT""", (self.id,), log_exceptions=False, ) except OperationalError as e: # User friendly error if the lock could not be claimed if getattr(e, "pgcode", None) == "55P03": raise exceptions.Warning(_("Another process/thread is already busy " "executing this job")) raise _logger.info("Job `%s` triggered from form", self.name) # Do not propagate active_test to the method to execute ctx = dict(self.env.context) ctx.pop("active_test", None) # Execute the cron job method = getattr(self.with_context(ctx).sudo(self.user_id).env[self.model], self.function) args = safe_eval("tuple(%s)" % (self.args or "")) return method(*args)
def write(self, vals): if 'content' in vals: vals['content'] = self._update_content(vals['content'], self.forum_id.id) if 'state' in vals: if vals['state'] in ['active', 'close'] and any(not post.can_close for post in self): raise KarmaError('Not enough karma to close or reopen a post.') if 'active' in vals: if any(not post.can_unlink for post in self): raise KarmaError('Not enough karma to delete or reactivate a post') if 'is_correct' in vals: if any(not post.can_accept for post in self): raise KarmaError('Not enough karma to accept or refuse an answer') # update karma except for self-acceptance mult = 1 if vals['is_correct'] else -1 for post in self: if vals['is_correct'] != post.is_correct and post.create_uid.id != self._uid: post.create_uid.sudo().add_karma(post.forum_id.karma_gen_answer_accepted * mult) self.env.user.sudo().add_karma(post.forum_id.karma_gen_answer_accept * mult) if any(key not in ['state', 'active', 'is_correct', 'closed_uid', 'closed_date', 'closed_reason_id'] for key in vals.keys()) and any(not post.can_edit for post in self): raise KarmaError('Not enough karma to edit a post.') res = super(Post, self).write(vals) # if post content modify, notify followers if 'content' in vals or 'name' in vals: for post in self: if post.parent_id: body, subtype = _('Answer Edited'), 'website_forum.mt_answer_edit' obj_id = post.parent_id else: body, subtype = _('Question Edited'), 'website_forum.mt_question_edit' obj_id = post obj_id.message_post(body=body, subtype=subtype) return res
class shipping_rate_wizard(models.TransientModel): _inherit = 'shipping.rate.wizard' @api.model def _get_company_code(self): res = super(shipping_rate_wizard, self)._get_company_code() res.append(('usps', 'USPS')) return res @api.model def default_get(self, fields): res = super(shipping_rate_wizard, self).default_get(fields) context = self._context if context.get('active_model', False) == 'sale.order': sale_id = context.get('active_id', False) if sale_id: sale = self.env['sale.order'].browse(sale_id) if 'usps_service_type' in fields and sale.usps_service_type: res['usps_service_type'] = sale.usps_service_type if 'usps_first_class_mail_type' in fields and sale.usps_first_class_mail_type: res['usps_first_class_mail_type'] = sale.usps_first_class_mail_type if 'usps_container' in fields and sale.usps_container: res['usps_container'] = sale.usps_container if 'usps_package_location' in fields and sale.usps_package_location: res['usps_package_location'] = sale.usps_package_location if 'usps_size' in fields and sale.usps_size: res['usps_size'] = sale.usps_size if 'usps_length' in fields and sale.usps_length: res['usps_length'] = sale.usps_length if 'usps_width' in fields and sale.usps_width: res['usps_width'] = sale.usps_width if 'usps_height' in fields and sale.usps_height: res['usps_height'] = sale.usps_height if 'usps_girth' in fields and sale.usps_girth: res['usps_girth'] = sale.usps_girth return res @api.multi def update_sale_order(self): ids = self._ids context = self._context data = self.browse(ids)[0] if not (data['rate_selection'] == 'rate_request' and data['ship_company_code'] == 'usps'): return super(shipping_rate_wizard, self).update_sale_order() if context.get('active_model', False) == 'sale.order': sale_id = context.get('active_id', False) sale_id and self.env['sale.order'].write({'shipcharge':data.shipping_cost, 'ship_method':data.usps_service_type, 'sale_account_id':data.logis_company and data.logis_company.ship_account_id and data.logis_company.ship_account_id.id or False, 'ship_company_code' :data.ship_company_code, 'logis_company' : data.logis_company and data.logis_company.id or False, 'usps_service_type' : data.usps_service_type, 'usps_package_location' : data.usps_package_location, 'usps_first_class_mail_type' : data.usps_first_class_mail_type , 'usps_container' : data.usps_container , 'usps_size' : data.usps_size , 'usps_length' : data.usps_length , 'usps_width' : data.usps_width , 'usps_height' : data.usps_height , 'usps_girth' : data.usps_girth , 'rate_selection' : data.rate_selection }) self.env['sale.order'].button_dummy([sale_id]) return {'nodestroy':False, 'type': 'ir.actions.act_window_close'} return True @api.multi def get_rate(self): ids = self._ids context = self._context data = self.browse(self._ids) if not (data['rate_selection'] == 'rate_request' and data['ship_company_code'] == 'usps'): return super(shipping_rate_wizard, self).get_rate() if context.get('active_model', False) == 'sale.order': sale_id = context.get('active_id', False) sale = self.env['sale.order'].browse(sale_id) test = data.logis_company.test_mode or False url = '' url_sec = '' if data.logis_company: url = test and data.logis_company.usps_url_test or data.logis_company.usps_url url_sec = test and data.logis_company.usps_url_secure_test or data.logis_company.usps_url_secure url_prd = data.logis_company.usps_url address_from = sale.company_id.partner_id and sale.company_id.partner_id zip_origin = '' if address_from: zip_origin = address_from.zip or '' zip_destination = sale.partner_shipping_id.zip or '' weight = math.modf(sale.total_weight_net) pounds = int(weight[1]) ounces = round(weight[0], 2) * 16 request_xml = """<RateV4Request USERID="%(user_id)s"> <Revision/> <Package ID="1ST"> <Service>%(service_type)s</Service> <FirstClassMailType>%(first_class_mail_type)s</FirstClassMailType> <ZipOrigination>%(zip_origin)s</ZipOrigination> <ZipDestination>%(zip_desitination)s</ZipDestination> <Pounds>%(pounds)s</Pounds> <Ounces>%(ounces)s</Ounces> <Container>%(container)s</Container> <Size>REGULAR</Size> <Machinable>true</Machinable> </Package> </RateV4Request>""" % { 'user_id' : data.logis_company and data.logis_company.usps_userid, 'service_type' : data.usps_service_type , 'first_class_mail_type' : data.usps_first_class_mail_type, 'zip_origin' : zip_origin, 'zip_desitination' : zip_destination, 'pounds' : str(pounds), 'ounces' : str(ounces), 'container' : str(data.usps_container) , } if url_prd and request_xml: request_url = url_prd + '?API=RateV4&XML=' + request_xml # not supported with test accounts str_response = '' error = False try : f = urllib.urlopen(request_url) str_response = f.read() except Exception, e: self.write({'status_message': str(e)}) if str_response: xml_dic = xml2dic.main(str_response) if 'Error' in xml_dic.keys(): error = True for item in xml_dic.get('Error'): if 'Description' in item: self.write({'status_message': 'Error : ' + item['Description'] }) else: for pack in xml_dic['RateV4Response']: if 'Package' in pack: for item in pack['Package']: if 'Error' in item: error = True for i in item['Error']: if 'Description' in i: self.write({'status_message': 'Error : ' + i['Description'] }) break if error: break if error: break if not error: for pack in xml_dic['RateV4Response']: if 'Package' in pack: for item in pack['Package']: if 'Postage' in item: for i in item['Postage']: if 'Rate' in i: self.write({'status_message': '', 'shipping_cost': i['Rate'] }) sale.write({'shipcharge': float(i['Rate']) or 0.00, 'ship_method':data.ship_company_code + ':' + data.usps_service_type, 'status_message': ''}) return True mod, modid = self.env['ir.model.data'].get_object_reference('shipping_api_usps', 'view_for_shipping_rate_wizard_usps') return { 'name':_("Get Rate"), 'view_mode': 'form', 'view_id': modid, 'view_type': 'form', 'res_model': 'shipping.rate.wizard', 'type': 'ir.actions.act_window', 'target':'new', 'nodestroy': True, 'domain': '[]', 'res_id': ids[0], 'context':context, }
def split_row_col(pos): match = re.match(r"([a-z]+)([0-9]+)", pos, re.I) if not match: raise ValidationError(_('Position %s is not valid') % pos) col, row = match.groups() return col, int(row)
begin_rc = min(all_rc) col, row = split_row_col(max(all_rc)) end_rc = '%s%s' % (col, max_row) worksheet_range[sheet_name] = '%s:%s' % (begin_rc, end_rc) # ================ BI Function ================ self._fill_bi(workbook, data_dict, worksheet_range) except KeyError, e: raise except_orm(_('Key Error!'), e) except IllegalCharacterError, e: raise except_orm( _('IllegalCharacterError!\n' 'Some exporting data may contain special character'), e) except Exception, e: raise except_orm(_('Error filling data into excel sheets!'), e) @api.model def _get_field_data(self, _field, _line): """ Get field data, and convert data type if needed """ if not _field: return None line_copy = _line for f in _field.split('.'): data_type = line_copy._fields[f].type line_copy = line_copy[f] if data_type == 'date': if line_copy: line_copy = dt.strptime(line_copy, '%Y-%m-%d') elif data_type == 'datetime': if line_copy:
def get_state(self): self.get_connection() raise Warning(_('Not implemented yet!'))
def confirm(self): if not self.is_compatible(): raise Warning(_("Only females can be farrow")) if not self.is_ready(): raise Warning( _("Only diagnosticated pregnant females can be farrow")) if self.dead == 0 and self.live == 0: raise Warning(_('no deads and no lives')) company = self.env['res.company'].search([(True, '=', True)])[0] journal = self.env['account.analytic.journal'].search([('code', '=', 'FAR')]) analytic_line_obj = self.env['account.analytic.line'] farrowing_cycle_obj = self.env['farm.farrowing.event_female_cycle'] farrrowing_animalGroup_obj = self.env['farm.farrowing.event_group'] location_obj = self.env['farm.foster.locations'] foster_locations = [] for loc in self.animal.specie.foster_location: foster_locations.append(loc.id) print loc.location print loc.location.location_id print foster_locations print self.farm.id foster_location = location_obj.search([ ('location.location_id.location_id', '=', self.farm.id), ('id', 'in', foster_locations), ], ).location print foster_location farrowing_cycle_obj.create({ 'event': self.id, 'cycle': self.animal.cycles[-1].id }) if self.live != 0: self.get_female_move(foster_location) new_group = self.get_produced_group() farrrowing_animalGroup_obj.create({ 'event': self.id, 'animal_group': new_group[0].id }) self.animal.current_cycle.update_state(self) tot_cost = 0 for line in self.animal.account.line_ids: tot_cost = tot_cost + line.amount analytic_line_obj.create({ 'name': 'Farrow Cost', 'date': self.timestamp, 'ref': 'farrow', 'amount': tot_cost, 'unit_amount': 1, 'account_id': new_group[0].account.id, 'general_account_id': company.feed_account.id, 'journal_id': journal.id, }) analytic_line_obj.create({ 'name': 'Farrow Cost', 'date': self.timestamp, 'ref': 'farrow', 'amount': -(tot_cost), 'unit_amount': 1, 'account_id': self.animal.account.id, 'general_account_id': company.feed_account.id, 'journal_id': journal.id, }) super(FarrowingEvent, self).confirm()
def _get_sds_states(self): return [('draft', _('Draft')), ('start', _('Start')), ('waiting_welcome', _('Waiting welcome')), ('active', _('Active')), ('field_memo', _('Field memo')), ('sub_waiting', _('Sub waiting')), ('sub', _('Sub')), ('sub_accept', _('Sub Accept')), ('sub_reject', _('Sub Reject')), ('inform_no_sub', _('Inform No sub')), ('no_sub', _('No sub')), ('cancelled', _('Cancelled'))]
class ClaimLine(models.Model): _name = "claim.line" _order = "date, priority desc" _inherit = 'mail.thread' _description = "List of product to return" _rec_name = "display_name" SUBJECT_LIST = [('none', 'Not specified'), ('legal', 'Legal retractation'), ('cancellation', 'Order cancellation'), ('damaged', 'Damaged delivered product'), ('error', 'Shipping error'), ('exchange', 'Exchange request'), ('lost', 'Lost during transport'), ('perfect_conditions', 'Perfect Conditions'), ('imperfection', 'Imperfection'), ('physical_damage_client', 'Physical Damage by Client'), ('physical_damage_company', 'Physical Damage by Company'), ('other', 'Other')] WARRANT_COMMENT = [('valid', _("Valid")), ('expired', _("Expired")), ('not_define', _("Not Defined"))] number = fields.Char(readonly=True, default='/', help='Claim Line Identification Number') company_id = fields.Many2one('res.company', string='Company', readonly=False, change_default=True, default=lambda self: self.env['res.company']. _company_default_get('claim.line')) date = fields.Date('Claim Line Date', select=True, default=fields.date.today()) name = fields.Text('Description', default='none', required=True, help="More precise description of the problem") priority = fields.Selection([('0_not_define', 'Not Define'), ('1_normal', 'Normal'), ('2_high', 'High'), ('3_very_high', 'Very High')], 'Priority', store=True, compute='_compute_priority', inverse='_inverse_priority', help="Priority attention of claim line") claim_diagnosis = fields.Selection([('damaged', 'Product Damaged'), ('repaired', 'Product Repaired'), ('good', 'Product in good condition'), ('hidden', 'Product with hidden physical ' 'damage')], help="To describe the line product " "diagnosis") claim_origin = fields.Selection(SUBJECT_LIST, 'Subject', required=True, help="To describe the " "line product problem") product_id = fields.Many2one('product.product', string='Product', help="Returned product") product_returned_quantity = fields.Float('Quantity', digits=(12, 2), help="Quantity of product " "returned") unit_sale_price = fields.Float(digits=(12, 2), help="Unit sale price of the product. " "Auto filled if return done " "by invoice selection. Be careful " "and check the automatic " "value as don't take into account " "previous refunds, invoice " "discount, can be for 0 if product " "for free,...") return_value = fields.Float(compute='_compute_line_total_amount', string='Total return', help="Quantity returned * Unit sold price",) prodlot_id = fields.Many2one('stock.production.lot', string='Serial/Lot number', help="The serial/lot of the returned product") applicable_guarantee = fields.Selection([('us', 'Company'), ('supplier', 'Supplier'), ('brand', 'Brand manufacturer')], 'Warranty type') guarantee_limit = fields.Date('Warranty limit', readonly=True, help="The warranty limit is " "computed as: invoice date + warranty " "defined on selected product.") warning = fields.Selection(WARRANT_COMMENT, 'Warranty', readonly=True, help="If warranty has expired") display_name = fields.Char('Name', compute='_compute_display_name') date_deadline = fields.Date(related="claim_id.date_deadline") priority_date = fields.Date(compute='_compute_priority_date') @api.model def get_warranty_return_partner(self): return self.env['product.supplierinfo'].get_warranty_return_partner() warranty_type = fields.Selection( get_warranty_return_partner, readonly=True, help="Who is in charge of the warranty return treatment towards " "the end customer. Company will use the current company " "delivery or default address and so on for supplier and brand " "manufacturer. Does not necessarily mean that the warranty " "to be applied is the one of the return partner (ie: can be " "returned to the company and be under the brand warranty") warranty_return_partner = fields.Many2one('res.partner', string='Warranty Address', help="Where the customer has to " "send back the product(s)") claim_id = fields.Many2one('crm.claim', string='Related claim', ondelete='cascade', 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')], string='State', default='draft') substate_id = fields.Many2one('substate.substate', string='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(string='Last change', help="To set the" "last state / substate change") invoice_line_id = fields.Many2one('account.invoice.line', string='Invoice Line', help='The invoice line related' ' to the returned product') refund_line_id = fields.Many2one('account.invoice.line', string='Refund Line', help='The refund line related' ' to the returned product') move_in_id = fields.Many2one('stock.move', string='Move Line from picking in', help='The move line related' ' to the returned product') move_out_id = fields.Many2one('stock.move', string='Move Line from picking out', help='The move line related' ' to the returned product') location_dest_id = fields.Many2one('stock.location', string='Return Stock Location', help='The return stock location' ' of the returned product') claim_type = fields.Many2one(related='claim_id.claim_type', string="Claim Line Type", store=True, help="Claim classification") invoice_date = fields.Date(related='invoice_line_id.invoice_id.' 'date_invoice', help="Date of Claim Invoice") # Method to calculate total amount of the line : qty*UP @api.multi def _compute_line_total_amount(self): for line in self: line.return_value = (line.unit_sale_price * line.product_returned_quantity) @api.multi def copy(self, default=None): self.ensure_one() default = default or {} std_default = { 'move_in_id': False, 'move_out_id': False, 'refund_line_id': False, } std_default.update(default) return super(ClaimLine, self).copy(default=std_default) @api.model def _get_priority_level(self): priority_max = self.env.user.company_id.priority_maximum priority_min = self.env.user.company_id.priority_minimum priority = "0_not_define" if self.invoice_date: days = fields.datetime.strptime(self.date, "%Y-%m-%d") - \ fields.datetime.strptime(self.invoice_date, DEFAULT_SERVER_DATE_FORMAT) if days.days <= priority_max: priority = "3_very_high" elif priority_max < days.days <= priority_min: priority = "2_high" elif days.days > priority_min: priority = "1_normal" return priority @api.depends("priority_date", "invoice_line_id.invoice_id.date_invoice") def _compute_priority(self): """To determine the priority of claim line """ for line_id in self: line_id.priority = line_id._get_priority_level() @api.multi def _compute_priority_date(self): for line_id in self: line_id.priority_date = line_id.claim_id.date @api.multi def _inverse_priority(self): """To determine the priority of claim line """ support_group_id = self.env.ref('crm_claim_rma.group_rma_user') support_user_ids = support_group_id.users # Internal claims are created by warehouse users and they are not # allowed to edit supplier claims, but create supplier claims # can be created from internal ones, so if a user is validating # an internal claims this calculation should be applied. from_internal_claim = self.env.context.get( 'validate_internal_claim', False) if not from_internal_claim and self.env.user not in support_user_ids: raise exceptions.ValidationError( _("You must belong to the group '%s' in order to be " "allowed to set priority level") % support_group_id.name ) # Having priority level and invoice date an aproximation of # claim date can be computed priority_max = self.env.user.company_id.priority_maximum priority_min = self.env.user.company_id.priority_minimum for line_id in self: invoice_date = line_id.invoice_line_id.invoice_id.date_invoice # functionally this is not possible, but tested for # default values if not invoice_date: continue days = priority_min + 1 if line_id.priority == "3_very_high": days = priority_max elif line_id.priority == "2_high": days = (priority_max + priority_min) * .5 line_id.priority_date = fields.datetime.strptime( invoice_date, DEFAULT_SERVER_DATE_FORMAT) + timedelta(days=days) def _get_subject(self, num): """Based on a subject number given, it returns the proper subject value only if the number is between the limits, in counter case is the first value of SUBJECT_LIST will be returned """ subject_index = num - 1 if 0 < num <= len(self.SUBJECT_LIST) else 0 return self.SUBJECT_LIST[subject_index][0] @staticmethod def warranty_limit(start, warranty_duration): """Take a duration in float, return the duration in relativedelta ``relative_delta(months=...)`` only accepts integers. We have to extract the decimal part, and then, extend the delta with days. """ decimal_part, months = math.modf(warranty_duration) months = int(months) # If we have a decimal part, we add the number them as days to # the limit. We need to get the month to know the number of # days. delta = relativedelta(months=months) monthday = start + delta __, days_month = calendar.monthrange(monthday.year, monthday.month) # ignore the rest of the days (hours) since we expect a date days = int(days_month * decimal_part) return start + relativedelta(months=months, days=days) def _get_warranty_limit_values(self, invoice, claim_type, product, claim_date): """Calculate the warranty of claim line product depending of invoice date. """ if not (invoice and claim_type and product and claim_date): return {'guarantee_limit': False, 'warning': False} # If the invoice has invoice date, the warranty of # damaged product can be calculated invoice_date = invoice.date_invoice if not invoice_date: raise InvoiceNoDate # First, the warranty is set as not defined warning = 'not_define' # The invoice date is converted to DATE FORMAT invoice_date = datetime.strptime(invoice_date, DEFAULT_SERVER_DATE_FORMAT) warranty_duration = False # If claim is supplier type, then, search the warranty specified for # the supplier in the suppliers configured for the damaged product. supplier_type = self.env.ref('crm_claim_rma.crm_claim_type_supplier') if claim_type == supplier_type: seller_id = product.seller_ids.filtered( lambda r: r.name == invoice.partner_id) if not seller_id: raise ProductNoSupplier warranty_duration = seller_id.warranty_duration if not warranty_duration: raise exceptions.Warning( _("Supplier warranty period for one or more products in " "your claim is(are) not set")) else: # If the claim is not supplier type, then, take the basic warranty # configured in the product warranty_duration = product.warranty # Get the limit_date limit_date = self.warranty_limit(invoice_date, warranty_duration) claim_date = datetime.strptime(claim_date, DEFAULT_SERVER_DATETIME_FORMAT) # Warranty is valid only when claim date is lesser than limit date, # in counter case the warranty is expired warning = 'valid' if claim_date <= limit_date else 'expired' # if the conditions above are not met, then, the warranty # is not defined limit_date = limit_date.strftime(DEFAULT_SERVER_DATE_FORMAT) return {'guarantee_limit': limit_date, 'warning': warning} def set_warranty_limit(self): self.ensure_one() claim_id = self.claim_id invoice_id = self.invoice_line_id.invoice_id values = self._get_warranty_limit_values( invoice_id, claim_id.claim_type, self.product_id, claim_id.date) self.write(values) return True @api.returns('stock.location') def get_destination_location(self, product_id, warehouse_id): """Compute and return the destination location to take for a return. Always take 'Supplier' one when return type different from company. """ location_dest_id = warehouse_id.lot_stock_id seller_id = product_id.seller_ids and product_id.seller_ids[0] if seller_id and seller_id.warranty_return_partner != 'company' \ and seller_id.name \ and seller_id.name.property_stock_supplier: location_dest_id = seller_id.name.property_stock_supplier return location_dest_id def _warranty_return_address_values(self, product, company, warehouse): """Return the partner to be used as return destination and the destination stock location of the line in case of return. We can have various cases here: - company or other: return to company partner or crm_return_address_id if specified - supplier: return to the supplier address """ if not (product and company and warehouse): return { 'warranty_return_partner': False, 'warranty_type': False, 'location_dest_id': False } seller_ids = product.seller_ids if seller_ids: seller_id = seller_ids[0] return_address_id = seller_id.warranty_return_address return_type = seller_id.warranty_return_partner else: # when no supplier is configured, returns to the company return_address_id = (company.crm_return_address_id or company.partner_id) return_type = 'company' location_dest = self.get_destination_location(product, warehouse) return { 'warranty_return_partner': return_address_id.id, 'warranty_type': return_type, 'location_dest_id': location_dest.id } def set_warranty_return_address(self): self.ensure_one() claim_id = self.claim_id values = self._warranty_return_address_values( self.product_id, claim_id.company_id, claim_id.warehouse_id) self.write(values) return True @api.multi def set_warranty(self): """Calculate warranty limit and address """ for line_id in self: if not line_id.product_id: raise exceptions.Warning( _('Error'), _('Please set product first')) # 因为售后单由sale.order生成,不存在发票明细,忽略此判断 # if not line_id.invoice_line_id: # raise exceptions.Warning( # _('Error'), _('Please set invoice first')) # line_id.set_warranty_limit() line_id.set_warranty_return_address() return True @api.model def _get_sequence_number(self): """@return the value of the sequence for the number field in the claim.line model. """ return self.env['ir.sequence'].get('claim.line') @api.model def create(self, vals): """@return write the identify number once the claim line is create. """ vals = vals or {} if ('number' not in vals) or (vals.get('number', False) == '/'): vals['number'] = self._get_sequence_number() res = super(ClaimLine, self).create(vals) return res @api.multi def _compute_display_name(self): for line_id in self: line_id.display_name = "%s - %s" % ( line_id.claim_id.code, line_id.name) @api.multi def name_get(self): names = [] for line_id in self: names.append((line_id.id, "%s - %s" % (line_id.claim_id.code, line_id.name))) return names
def _check_hierarchy(self): if not self._check_recursion(): raise models.ValidationError(_( 'Error! You cannot create recursive calendars.'))
def action_number(self): msg = self.check_data() if msg != '': raise except_orm(_('Date Inconsistency'), msg) super(account_invoice, self).action_number() return True
def copy(self, default=None): default = dict(default or {}) default['shortdesc'] = _('%s (copy)') % self.shortdesc return super(Module, self).copy(default)
def cancel(self): """ Reject the change """ if any(change.state == 'done' for change in self): raise exceptions.Warning(_('This change has already be applied.')) self.set_old_value() self.write({'state': 'cancel'})
def action_reconcile(self): for rec in self: # Clear old matching rec.item_ids.write({'match_import_id': False}) rec.item_ids.mapped('move_line_id').\ write({'match_import_id': False}) # on move line rec.import_ids.write({'match_import_id': False}) match_criteria = rec._get_match_criteria() if not match_criteria: raise ValidationError(_('No Reconcile Patter found!')) # Update Book (items) rec._cr.execute(""" update pabi_bank_statement_item book set match_import_id = (select import.id from pabi_bank_statement_item item join pabi_bank_statement_import import on %s where item.id = book.id and item.statement_id = %s and import.statement_id = %s limit 1) where statement_id = %s """ % (match_criteria, rec.id, rec.id, rec.id)) # Update move line's match_item_id rec._cr.execute(""" update account_move_line move set match_import_id = (select item.match_import_id from account_move_line move2 join pabi_bank_statement_item item on item.move_line_id = move2.id where move.id = move2.id and item.statement_id = %s limit 1) where id in (select move_line_id from pabi_bank_statement_item where statement_id = %s) """ % (rec.id, rec.id)) # Update Bank (import), based on what already matched rec._cr.execute(""" update pabi_bank_statement_import bank set match_item_id = (select item.id from pabi_bank_statement_item item where item.match_import_id = bank.id and statement_id = %s limit 1) where statement_id = %s """ % (rec.id, rec.id)) # Finally, if some line was matched before in other statement rec._cr.execute(""" update pabi_bank_statement_import new set prev_match_statement_id = (select statement_id from pabi_bank_statement_import old where old.debit = new.debit and old.credit = new.credit and (old.document = new.document or old.cheque_number = new.cheque_number) and old.match_item_id is not null limit 1) where match_item_id is null and statement_id = %s """ % (rec.id, )) self.write({'state': 'reconcile'}) return
def crear_recibo(self): if self.solicitud_anticipos_id: account_voucher_obj = self.env['account.voucher'] partner = self.employee_id.address_home_id if self.diferencia > 0: if self.journal_id and self.journal_id.type == 'purchase': journal_id = self.journal_id else: search_args = [('type', '=', 'purchase')] if self.env.user.company_id.currency_id.id != self.currency_id.id: search_args.append( ('currency', '=', self.currency_id.id)) else: search_args.extend([ '|', ('currency', '=', False), ('currency', '=', self.env.user.company_id.currency_id.id) ]) journal_id = self.env['account.journal'].search( search_args, limit=1) if journal_id: account_id = partner.property_account_payable if not account_id: account_id = journal_id.default_credit_account_id if not account_id: raise exceptions.ValidationError( _(u'Error, debe configurar la cuenta a pagar' u' del beneficierio o del diario contable utilizado.' )) sa_line_id = len( self.solicitud_anticipos_id.line_ids ) and self.solicitud_anticipos_id.line_ids[0] or False account_voucher_id = account_voucher_obj.create({ 'partner_id': partner.id or False, 'date': fields.date.today(), 'journal_id': journal_id.id, 'type': 'payment', 'account_id': account_id.id, 'amount': abs(self.diferencia), 'payment_rate': 0, 'operating_unit_id': self.solicitud_anticipos_id.operating_unit_id.id, 'solicitud_anticipos_id': self.solicitud_anticipos_id.id, 'rendicion_anticipos_id': self.id, 'line_dr_ids': [(0, 0, { 'concept_id': sa_line_id and sa_line_id.concept_id.id or False, 'account_id': sa_line_id and sa_line_id.account_id.id or False, 'amount_unreconciled': abs(self.diferencia), 'amount': abs(self.diferencia), 'journal_id': journal_id.id or False, 'partner_id': partner.id or False, })] }) tipo_ejecucion = self.env['tipo.ejecucion.siif'].search([ ('codigo', '=', 'P') ]) invoice_id = self.env['account.invoice'].create({ 'partner_id': account_voucher_id.partner_id.id, 'account_id': account_voucher_id.account_id.id, 'date_invoice': account_voucher_id.date, 'internal_number': account_voucher_id.number, 'number': account_voucher_id.number, 'currency_id': account_voucher_id.currency_id.id, 'siif_tipo_ejecucion': tipo_ejecucion and tipo_ejecucion.id or False, 'type': 'in_invoice', 'amount_total': abs(self.diferencia), 'pago_aprobado': False, 'doc_type': 'vales_caja', 'state': 'open', 'invoice_line': [(0, 0, { 'name': line.name or '', 'account_id': line.account_id.id, 'price_unit': line.amount }) for line in account_voucher_id.line_dr_ids] }) account_voucher_id.write({'invoice_id': invoice_id.id}) invoice_id.write({'doc_type': 'vales_caja'}) else: raise exceptions.ValidationError( _(u'Error, debe seleccionar un diario compra' u' o configurar un diario de compra de la compañia.') ) else: if self.journal_id and self.journal_id.type == 'sale': journal_id = self.journal_id else: search_args = [('type', '=', 'sale')] if self.env.user.company_id.currency_id.id != self.currency_id.id: search_args.append( ('currency', '=', self.currency_id.id)) else: search_args.extend([ '|', ('currency', '=', False), ('currency', '=', self.env.user.company_id.currency_id.id) ]) journal_id = self.env['account.journal'].search( search_args, limit=1) if journal_id: account_id = partner.property_account_receivable if not account_id: account_id = journal_id.default_debit_account_id if not account_id: raise exceptions.ValidationError( _(u'Error, debe configurar la cuenta a cobrar' u' del beneficierio o del diario contable utilizado.' )) # product_id = self.solicitud_anticipos_id and self.sudo().operating_unit_id.anticipo_product_id product_id = self.get_anticipo_product() if not product_id: raise ValidationError( _(u"Debe configurar un producto Dev. Anticipos para la Unidad ejecutora seleccionada!" )) # raise ValidationError(_(u"Debe configurar un producto con la opción 'Devolución de anticipos' seleccionada!")) account_voucher_id = account_voucher_obj.create({ 'partner_id': partner.id or False, 'date': fields.date.today(), 'journal_id': journal_id.id, 'type': 'sale', 'account_id': account_id.id, 'amount': abs(self.diferencia), 'payment_rate': 0, 'operating_unit_id': self.solicitud_anticipos_id.operating_unit_id.id, 'rendicion_anticipos_id': self.id, 'solicitud_anticipos_id': self.solicitud_anticipos_id.id, 'line_cr_ids': [(0, 0, { 'account_id': partner.customer_advance_account_id.id, 'amount_unreconciled': abs(self.diferencia), 'amount': abs(self.diferencia), 'journal_id': journal_id.id or False, 'partner_id': partner.id or False, 'product_id': product_id.id })] }) account_voucher_id.proforma_voucher() else: raise exceptions.ValidationError( _(u'Error, debe seleccionar un diario venta' u' o configurar un diario de venta de la compañia.')) else: super(GrpRendicionAnticipos, self).crear_recibo() return True
def check_no_same_task(self): if self.task_id == self.predecessor_task_id: raise UserError( _("You can not select itself for predecessor/sucessor"))
def generate_csv_report(self, _p, _xs, data, objects, wb): report_name = _("Faktur Keluaran") ws = wb.add_sheet(report_name[:31]) ws.panes_frozen = True ws.remove_splits = True ws.portrait = 0 # Landscape ws.fit_width_to_pages = 1 row_pos = 0 # set print header/footer ws.header_str = self.xls_headers['standard'] ws.footer_str = self.xls_footers['standard'] c_row_cell_style = xlwt.easyxf(num_format_str='###0') # Column headers 1 c_specs = [ ('FK', 1, 0, 'text', 'FK'), ('KD_JENIS_TRANSAKSI', 1, 0, 'text', 'KD_JENIS_TRANSAKSI'), ('FG_PENGGANTI', 1, 0, 'text', 'FG_PENGGANTI'), ('NOMOR_FAKTUR', 1, 0, 'text', 'NOMOR_FAKTUR'), ('MASA_PAJAK', 1, 0, 'text', 'MASA_PAJAK'), ('TAHUN_PAJAK', 1, 0, 'text', 'TAHUN_PAJAK'), ('TANGGAL_FAKTUR', 1, 0, 'text', 'TANGGAL_FAKTUR'), ('NPWP', 1, 0, 'text', 'NPWP'), ('NAMA', 1, 0, 'text', 'NAMA'), ('ALAMAT_LENGKAP', 1, 0, 'text', 'ALAMAT_LENGKAP'), ('JUMLAH_DPP', 1, 0, 'text', 'JUMLAH_DPP'), ('JUMLAH_PPN', 1, 0, 'text', 'JUMLAH_PPN'), ('JUMLAH_PPNBM', 1, 0, 'text', 'JUMLAH_PPNBM'), ('ID_KETERANGAN_TAMBAHAN', 1, 0, 'text', 'ID_KETERANGAN_TAMBAHAN'), ('FG_UANG_MUKA', 1, 0, 'text', 'FG_UANG_MUKA'), ('UANG_MUKA_DPP', 1, 0, 'text', 'UANG_MUKA_DPP'), ('UANG_MUKA_PPN', 1, 0, 'text', 'UANG_MUKA_PPN'), ('UANG_MUKA_PPNBM', 1, 0, 'text', 'UANG_MUKA_PPNBM'), ('REFERENSI', 1, 0, 'text', 'REFERENSI'), ] row_data = self.xls_row_template(c_specs, [x[0] for x in c_specs]) row_pos = self.xls_write_row(ws, row_pos, row_data, row_style=c_row_cell_style) # Column headers 2 c_specs = [ ('LT', 1, 0, 'text', 'LT'), ('NPWP', 1, 0, 'text', 'NPWP'), ('NAMA', 1, 0, 'text', 'NAMA'), ('JALAN', 1, 0, 'text', 'JALAN'), ('BLOK', 1, 0, 'text', 'BLOK'), ('NOMOR', 1, 0, 'text', 'NOMOR'), ('RT', 1, 0, 'text', 'RT'), ('RW', 1, 0, 'text', 'RW'), ('KECAMATAN', 1, 0, 'text', 'KECAMATAN'), ('KELURAHAN', 1, 0, 'text', 'KELURAHAN'), ('KABUPATEN', 1, 0, 'text', 'KABUPATEN'), ('PROPINSI', 1, 0, 'text', 'PROPINSI'), ('KODE_POS', 1, 0, 'text', 'KODE_POS'), ('NOMOR_TELEPON', 1, 0, 'text', 'NOMOR_TELEPON'), ] row_data = self.xls_row_template(c_specs, [x[0] for x in c_specs]) row_pos = self.xls_write_row(ws, row_pos, row_data, row_style=c_row_cell_style) # Column headers 3 c_specs = [ ('OF', 1, 0, 'text', 'OF'), ('KODE_OBJEK', 1, 0, 'text', 'KODE_OBJEK'), ('NAMA', 1, 0, 'text', 'NAMA'), ('HARGA_SATUAN', 1, 0, 'text', 'HARGA_SATUAN'), ('JUMLAH_BARANG', 1, 0, 'text', 'JUMLAH_BARANG'), ('HARGA_TOTAL', 1, 0, 'text', 'HARGA_TOTAL'), ('DISKON', 1, 0, 'text', 'DISKON'), ('DPP', 1, 0, 'text', 'DPP'), ('PPN', 1, 0, 'text', 'PPN'), ('TARIF_PPNBM', 1, 0, 'text', 'TARIF_PPNBM'), ('PPNBM', 1, 0, 'text', 'PPNBM'), ] row_data = self.xls_row_template(c_specs, [x[0] for x in c_specs]) row_pos = self.xls_write_row(ws, row_pos, row_data, row_style=c_row_cell_style) for inv in objects: c_specs = [ ('FK', 1, 0, 'text', 'FK'), ('kd_jenis_transaksi', 1, 0, 'text', '01'),#x['faktur_pajak_no'] and x['faktur_pajak_no'][:2] or '01' ('jenis_fp', 1, 0, 'text', '0'),#0=faktur pajak, 1=faktur pajak pengganti ('nomor_faktur', 1, 0, 'text', inv.nomor_faktur_id and inv.nomor_faktur_id.number or ''),#010.000-15.10897639 ('masa_pajak', 1, 0, 'number', int(time.strftime('%m', time.strptime(inv.date_invoice,'%Y-%m-%d')))), ('tahun_pajak', 1, 0, 'number', time.strftime('%Y', time.strptime(inv.date_invoice,'%Y-%m-%d'))), ('tanggal_faktur', 1, 0, 'text', time.strftime('%d/%m/%Y', time.strptime(inv.date_invoice,'%Y-%m-%d'))), ('npwp', 1, 0, 'text', inv.npwp_efaktur or '000000000000000'),#02.505.335.6-016.000 ('nama', 1, 0, 'text', _p.get_name_npwp(inv.partner_id, 'npwp') or ''), ('alamat_lengkap', 1, 0, 'text', _p.get_street_npwp(inv.partner_id, 'npwp') or ''), ('jumlah_dpp', 1, 0, 'number', int(inv.amount_untaxed)), ('jumlah_ppn', 1, 0, 'number', int(inv.amount_tax)), ('jumlah_ppnbm', 1, 0, 'number', 0), ('id_keterangan_tambahan', 1, 0, 'text', ''), ('fg_uang_muka', 1, 0, 'number', 0), ('uang_muka_dpp', 1, 0, 'number', 0), ('uang_muka_ppn', 1, 0, 'number', 0), ('uang_muka_ppnbm', 1, 0, 'number', 0), ('referensi', 1, 0, 'text', inv.name or inv.origin or ''), ] row_data = self.xls_row_template(c_specs, [x[0] for x in c_specs]) row_pos = self.xls_write_row(ws, row_pos, row_data, row_style=c_row_cell_style) #Faktur Company #=================================================================== # c_specs = [ # ('FAPR', 1, 0, 'text', 'FAPR'), # ('company_name', 1, 0, 'text', inv.partner_id.name), # ('company_address', 1, 0, 'text', _p.get_street_npwp(inv.partner_id.id, 'npwp')), # ] # row_data = self.xls_row_template(c_specs, [x[0] for x in c_specs]) # row_pos = self.xls_write_row(ws, row_pos, row_data, row_style=c_row_cell_style) #=================================================================== for line in inv.invoice_line: c_specs = [ ('OF', 1, 0, 'text', 'OF'), ('code_product', 1, 0, 'text', line.product_id.default_code or ''), ('name_product', 1, 0, 'text', line.product_id.name or ''), ('price_unit', 1, 0, 'number', int(_p.amount_currency_line(line.price_subtotal/line.quantity, line))), ('quantity', 1, 0, 'number', line.quantity or 1), ('price_unit_quantity', 1, 0, 'number', int(_p.amount_currency_line(line.price_subtotal, line))), ('discount', 1, 0, 'number', line.discount or 0), ('dpp_product', 1, 0, 'number', int(_p.amount_currency_line(line.price_subtotal, line))), ('ppn_product', 1, 0, 'number', line.invoice_line_tax_id and int(_p.amount_currency_line(round(line.invoice_line_tax_id.amount*line.price_subtotal,2),line))), ('tarif_ppnbm', 1, 0, 'number', 0), ('ppnbm', 1, 0, 'number', 0), ] row_data = self.xls_row_template(c_specs, [x[0] for x in c_specs]) row_pos = self.xls_write_row(ws, row_pos, row_data, row_style=c_row_cell_style)
def button_cancel_remaining(self): """ Esta funcion es similar a la "cancel" de los procurements salvo que cancel solo sirve si no hay ningún move en done, con esta funcion cancelamos todo lo no done y chequeando que no haya cosas con "reservation" para no romper nada o que queden pedidos incompletos ( sobre todo para dos pasos). se llama recursivamente con related procurements ya que no podemos simplemente pasar en contexto "cancel_procurement" porque eso llamaria a "cancel" y si ya hubo entregas parciales no se van a cancelar los procuremets relacionados """ # no permitimos que se cancelen abastecimientos generados # automaticamente por moves porque queremos que se cancele el # abastecimiento padre mandamos esta clave en contexto para indicar si # se llama desde el padre from_move_dest = self._context.get('from_move_dest', False) for rec in self.filtered(lambda x: x.state != 'done'): if rec.move_dest_id and not from_move_dest: raise ValidationError( _('Solo puede cancelar abastecimientos primarios no los ' 'encadenados')) if rec.rule_id.action != 'move': raise ValidationError( _('Cancel remaining in procurements is only implmented for ' 'rules with action of type "move"')) not_done_moves = rec.move_ids.filtered(lambda x: x.state != 'done') # al final cancelamos por mas que este asignado siempre y cuando # no haya procurements relacionados que esten realizados # chequeamos contra reserver para que permita cancelar si se forzo # disponibilidad o para compras por ejemplo # if not_done_moves.filtered(lambda x: x.state == 'assigned'): # raise UserError(_( # 'You can not cancel a procurement if it has assigned ' # 'moves!')) # if not_done_moves.filtered(lambda x: x.reserved_quant_ids): # raise ValidationError(_( # 'You can not cancel a procurement if it has moves with ' # ' reserved quants!\n' # 'You should unreserve or confirm related pickings first') # verificamos en los moves y no en los procurements porque el proc # podria no estar totalmente satisfecho e igual queremos restringir # si al menos un move ya fue confirmado not_done_moves_related_moves = not_done_moves.search([ ('move_dest_id', 'in', not_done_moves.ids), ('state', '=', 'done'), ]) if not_done_moves_related_moves: raise ValidationError( _('You can not cancel moves that are destination moves ' 'of already done moves.\n' '* Moves to cancel: %s\n' '* Done moves: %s') % (not_done_moves.ids, not_done_moves_related_moves.ids)) not_done_moves.action_cancel() # ya no seria necesario porque modificamos el action_cancel # de los moves ya que no siempre este metodo borraba las operations # y quedaban en algunos casos moves cancelados con operations # because cancel dont update operations, we re asign # not_done_moves.mapped('picking_id').filtered( # lambda x: x.state not in ['draft', 'cancel']).action_assign() # al fina buscamos en todos los moves relacionados # porque los procurements generados (y parcialmente satsifechos) # podrian estar ligados a un move realizado related_procurements = rec.search( # [('move_dest_id', 'in', not_done_moves.ids)]) [('move_dest_id', 'in', rec.move_ids.ids)]) related_procurements.with_context( from_move_dest=True).button_cancel_remaining() rec.check()
def _get_reporting_level(self): return [('standard', _('Standard')), ('extended', _('Extended'))]
def action_move_create(self): account_move_obj = self.env['account.move'] account_move_line_obj = self.env['account.move.line'] cur_obj = self.pool.get('res.currency') for rec in self: if not rec.employee_id.address_home_id: raise exceptions.ValidationError( _(u'El empleado debe tener una dirección de casa.')) if not rec.employee_id.address_home_id.supplier_advance_account_id.id or not rec.employee_id.address_home_id.customer_advance_account_id.id: raise exceptions.ValidationError( _(u'El empleado debe tener las cuentas anticipos de proveedores y clientes establecida en su dirección de casa.' )) if len(rec.line_ids) > 0: # create the move that will contain the accounting entries account_move_dict = rec.account_move_get(rec.id) account_move_dict.update( {'operating_unit_id': rec.operating_unit_id.id}) move_id = account_move_obj.create(account_move_dict) company_currency = rec.company_id.currency_id.id diff_currency_p = rec.currency_id.id <> company_currency currency_id = False amount = rec.amount amount_currency = False if diff_currency_p: amount_currency = rec.amount * -1 currency_id = rec.currency_id.id amount = cur_obj.compute(self._cr, self._uid, currency_id, company_currency, rec.amount, self._context) for linea in rec.line_ids: property_obj = self.pool.get('ir.property') if rec.solicitud_anticipos_id: acc = linea.account_concept_id elif linea.product_id: acc = linea.product_id.property_account_expense if not acc: acc = linea.product_id.categ_id.property_account_expense_categ if not acc: raise exceptions.ValidationError( _(u'No se ha encontrado una cuenta de compras para el producto %s (o para su categoría). Por favor, configure una.' ) % (linea.product_id.name)) else: acc = property_obj.with_context( force_company=linea.company_id.id).get( 'property_account_expense_categ', 'product.category') if not acc: raise exceptions.ValidationError( _(u'No se ha podido identificar una cuenta para generar la información contable' )) total_amount_currency = False total_amount = linea.total_amount if diff_currency_p: total_amount_currency = linea.total_amount total_amount = cur_obj.compute(self._cr, self._uid, currency_id, company_currency, linea.total_amount, self._context) account_move_line_obj.create({ 'move_id': move_id.id, 'name': '/', 'partner_id': rec.employee_id.address_home_id.id or False, 'amount_currency': total_amount_currency, 'currency_id': currency_id, 'account_id': acc.id, 'credit': False, 'debit': total_amount, 'operating_unit_id': rec.operating_unit_id.id }) if rec.doc_type == 'rendicion_anticipo': _account_id = rec.employee_id.address_home_id.customer_advance_account_id.id else: _account_id = rec.employee_id.address_home_id.supplier_advance_account_id.id if not _account_id: raise exceptions.ValidationError( _(u'No se ha podido identificar una cuenta para generar la información contable' )) account_move_line_obj.create({ 'move_id': move_id.id, # 28/12/2018 ASM renombrar sequence (nombre reservado) a x_sequence # 'name': rec.sequence, 'name': rec.x_sequence, # 'account_id': _account_id, 'debit': False, 'credit': amount, 'partner_id': rec.employee_id.address_home_id.id or False, 'amount_currency': amount_currency > 0 and amount_currency * -1 or amount_currency, 'currency_id': currency_id, 'operating_unit_id': rec.operating_unit_id.id }) dict_write = { 'account_move_id': move_id.id, 'show_move_line_button': False } if rec.diferencia == 0: dict_write.update({'state': 'paid'}) else: rec.crear_recibo() rec.write(dict_write) else: raise exceptions.ValidationError( _(u'Error, para generar apuntes contables' u' de la anticipos de fondos primero debe crear líneas')) return True
def _get_weight_and_supplunits(self, inv_line, hs_code): line_qty = inv_line.quantity product = inv_line.product_id invoice = inv_line.invoice_id intrastat_unit_id = hs_code.intrastat_unit_id source_uom = inv_line.uos_id weight_uom_categ = self._get_uom_refs('weight_uom_categ') kg_uom = self._get_uom_refs('kg_uom') pce_uom_categ = self._get_uom_refs('pce_uom_categ') pce_uom = self._get_uom_refs('pce_uom') weight = suppl_unit_qty = 0.0 if not source_uom: note = "\n" + _( "Missing unit of measure on the line with %d " "product(s) '%s' on invoice '%s'.") % ( line_qty, product.name_get()[0][1], invoice.number) note += "\n" + _("Please adjust this line manually.") self._note += note return weight, suppl_unit_qty if intrastat_unit_id: target_uom = intrastat_unit_id.uom_id if not target_uom: note = "\n" + _( "Conversion from Intrastat Supplementary Unit '%s' to " "Unit of Measure is not implemented yet." ) % intrastat_unit_id.name note += "\n" + _( "Please correct the Intrastat Supplementary Unit " "settings and regenerate the lines or adjust the lines " "with Intrastat Code '%s' manually") % hs_code.display_name self._note += note return weight, suppl_unit_qty if target_uom.category_id == source_uom.category_id: suppl_unit_qty = self.env['product.uom']._compute_qty_obj( source_uom, line_qty, target_uom) else: note = "\n" + _("Conversion from unit of measure '%s' to '%s' " "is not implemented yet.") % (source_uom.name, target_uom.name) note += "\n" + _( "Please correct the unit of measure settings and " "regenerate the lines or adjust the impacted " "lines manually") self._note += note return weight, suppl_unit_qty if source_uom == kg_uom: weight = line_qty elif source_uom.category_id == weight_uom_categ: weight = self.env['product.uom']._compute_qty_obj( source_uom, line_qty, kg_uom) elif source_uom.category_id == pce_uom_categ: if not product.weight_net: note = "\n" + _("Missing net weight on product %s." ) % product.name_get()[0][1] note += "\n" + _( "Please correct the product record and regenerate " "the lines or adjust the impacted lines manually") self._note += note return weight, suppl_unit_qty if source_uom == pce_uom: weight = product.weight_net * line_qty else: # Here, I suppose that, on the product, the # weight is per PCE and not per uom_id weight = product.weight_net * \ self.env['product.uom']._compute_qty_obj( source_uom, line_qty, pce_uom) else: note = "\n" + _( "Conversion from unit of measure '%s' to 'Kg' " "is not implemented yet. It is needed for product '%s'.") % ( source_uom.name, product.name_get()[0][1]) note += "\n" + _( "Please correct the unit of measure settings and " "regenerate the lines or adjust the impacted lines " "manually") self._note += note return weight, suppl_unit_qty return weight, suppl_unit_qty
def nfe_export(self): for data in self: active_ids = self._context.get("active_ids", []) if not active_ids: err_msg = u"Não existe nenhum documento fiscal para ser" u" exportado!" invoices = [] export_inv_numbers = [] company_ids = [] err_msg = "" for inv in self.env["account.invoice"].browse(active_ids): if inv.state not in ("sefaz_export"): err_msg += (u"O Documento Fiscal %s não esta definida para" u" ser exportação " u"para a SEFAZ.\n") % inv.fiscal_number elif not inv.issuer == "0": err_msg += (u"O Documento Fiscal %s é do tipo externa e " u"não pode ser exportada para a " u"receita.\n") % inv.fiscal_number else: inv.write({ "nfe_export_date": False, "nfe_access_key": False, "nfe_status": False, "nfe_date": False, }) message = ("O Documento Fiscal %s foi \ exportado." % inv.fiscal_number) invoices.append(inv) company_ids.append(inv.company_id.id) export_inv_numbers.append(inv.fiscal_number) if len(set(company_ids)) > 1: err_msg += (u"Não é permitido exportar Documentos Fiscais de " u"mais de uma empresa, por favor selecione " u"Documentos Fiscais da mesma empresa.") if len(export_inv_numbers) > 1: name = "nfes{}-{}.{}".format( time.strftime("%d-%m-%Y"), self.env["ir.sequence"].get("nfe.export"), data.file_type, ) else: name = "nfe{}.{}".format(export_inv_numbers[0], data.file_type) mod_serializer = __import__( ("openerp.addons.l10n_br_account_product" ".sped.nfe.serializer.") + data.file_type, globals(), locals(), data.file_type, ) func = getattr(mod_serializer, "nfe_export") for invoice in invoices: invoice.nfe_export_date = datetime.now() nfes = func(invoices, data.nfe_environment, inv.nfe_version) for nfe in nfes: nfe_file = nfe["nfe"].encode("utf8") data.write({ "file": base64.b64encode(nfe_file), "state": "done", "name": name }) if err_msg: raise UserError(_(err_msg)) view_rec = self.env.ref( "l10n_br_account_product." "l10n_br_account_product_nfe_export_invoice_form") view_id = view_rec and view_rec.id or False return { "view_type": "form", "view_id": [view_id], "view_mode": "form", "res_model": "l10n_br_account_product.nfe_export_invoice", "res_id": data.id, "type": "ir.actions.act_window", "target": "new", "context": data.env.context, }
def _check_year(self): for this in self: s = str(this.year) if len(s) != 4 or s[0] != '2': raise ValidationError(_("Invalid Year !"))
def _gather_invoices(self): lines = [] accessory_costs = self.company_id.intrastat_accessory_costs self._gather_invoices_init() domain = self._prepare_invoice_domain() invoices = self.env['account.invoice'].search(domain) for invoice in invoices: lines_current_invoice = [] total_inv_accessory_costs_cc = 0.0 # in company currency total_inv_product_cc = 0.0 # in company currency total_inv_weight = 0.0 for inv_line in invoice.invoice_line: if (accessory_costs and inv_line.product_id and inv_line.product_id.is_accessory_cost): acost = invoice.currency_id.with_context( date=invoice.date_invoice).compute( inv_line.price_subtotal, self.company_id.currency_id) total_inv_accessory_costs_cc += acost continue if not inv_line.quantity: _logger.info( 'Skipping invoice line %s qty %s ' 'of invoice %s. Reason: qty = 0' % (inv_line.name, inv_line.quantity, invoice.number)) continue partner_country = self._get_partner_country(inv_line) if not partner_country: _logger.info( 'Skipping invoice line %s qty %s ' 'of invoice %s. Reason: no partner_country' % (inv_line.name, inv_line.quantity, invoice.number)) continue if any([ tax.exclude_from_intrastat_if_present for tax in inv_line.invoice_line_tax_id ]): _logger.info( 'Skipping invoice line %s ' 'qty %s of invoice %s. Reason: ' 'tax.exclude_from_intrastat_if_present' % (inv_line.name, inv_line.quantity, invoice.number)) continue if inv_line.hs_code_id: hs_code = inv_line.hs_code_id elif inv_line.product_id and self._is_product(inv_line): hs_code = inv_line.product_id.product_tmpl_id.\ get_hs_code_recursively() if not hs_code: note = "\n" + _( "Missing H.S. code on product %s. " "This product is present in invoice %s.") % ( inv_line.product_id.name_get()[0][1], inv_line.invoice_id.number) self._note += note continue else: _logger.info( 'Skipping invoice line %s qty %s' 'of invoice %s. Reason: no product nor hs_code' % (inv_line.name, inv_line.quantity, invoice.number)) continue intrastat_transaction = \ self._get_intrastat_transaction(inv_line) weight, suppl_unit_qty = self._get_weight_and_supplunits( inv_line, hs_code) total_inv_weight += weight amount_company_currency = self._get_amount(inv_line) total_inv_product_cc += amount_company_currency product_origin_country = self._get_product_origin_country( inv_line) region = self._get_region(inv_line) line_vals = { 'parent_id': self.id, 'invoice_line_id': inv_line.id, 'src_dest_country_id': partner_country.id, 'product_id': inv_line.product_id.id, 'hs_code_id': hs_code.id, 'weight': weight, 'suppl_unit_qty': suppl_unit_qty, 'amount_company_currency': amount_company_currency, 'amount_accessory_cost_company_currency': 0.0, 'transaction_id': intrastat_transaction.id, 'product_origin_country_id': product_origin_country.id or False, 'region_id': region and region.id or False, } # extended declaration if self._extended: transport = self._get_transport(inv_line) line_vals.update({ 'transport_id': transport.id, }) self._update_computation_line_vals(inv_line, line_vals) if line_vals: lines_current_invoice.append((line_vals)) self._handle_invoice_accessory_cost(invoice, lines_current_invoice, total_inv_accessory_costs_cc, total_inv_product_cc, total_inv_weight) for line_vals in lines_current_invoice: if (not line_vals['amount_company_currency'] and not line_vals['amount_accessory_cost_company_currency'] ): inv_line = self.env['account.invoice.line'].browse( line_vals['invoice_line_id']) _logger.info('Skipping invoice line %s qty %s ' 'of invoice %s. Reason: price_subtotal = 0 ' 'and accessory costs = 0' % (inv_line.name, inv_line.quantity, inv_line.invoice_id.number)) continue lines.append(line_vals) return lines
def _prepare_order_line_invoice_line(self, cr, uid, line, account_id=False, context=None): """Prepare the dict of values to create the new invoice line for a sales order line. This method may be overridden to implement custom invoice generation (making sure to call super() to establish a clean extension chain). :param browse_record line: sale.order.line record to invoice :param int account_id: optional ID of a G/L account to force (this is used for returning products including service) :return: dict of values to create() the invoice line """ order = self.browse(cr, uid, line.id).order_id company = self.pool.get('res.company').browse(cr, uid, order.company_id.id) res = {} if not line.invoiced: if not account_id: if line.product_id: account_id = line.product_id.property_account_income.id if not account_id: account_id = line.product_id.categ_id.property_account_income_categ.id or company.property_account_income and company.property_account_income.id if not account_id: raise Warning(_('Error!'), _('Please define income account for this product: "%s" (id:%d).') % \ (line.product_id.name, line.product_id.id,)) else: prop = self.pool.get('ir.property').get( cr, uid, 'property_account_income_categ', 'product.category', context=context) account_id = prop and prop.id or False uosqty = self._get_line_qty(cr, uid, line, context=context) uos_id = self._get_line_uom(cr, uid, line, context=context) pu = 0.0 if uosqty: pu = round( line.price_unit * line.product_uom_qty / uosqty, self.pool.get('decimal.precision').precision_get( cr, uid, 'Product Price')) fpos = line.order_id.fiscal_position or False account_id = self.pool.get('account.fiscal.position').map_account( cr, uid, fpos, account_id) if not account_id: raise Warning( _('Error!'), _('There is no Fiscal Position defined or Income category account defined for default properties of Product categories.' )) res = { 'name': line.name, 'sequence': line.sequence, 'origin': line.order_id.name, 'account_id': account_id, 'price_unit': pu, 'quantity': uosqty, 'discount': line.discount, 'uos_id': uos_id, 'product_id': line.product_id.id or False, 'invoice_line_tax_id': [(6, 0, [x.id for x in line.tax_id])], 'account_analytic_id': line.order_id.project_id and line.order_id.project_id.id or False, } return res
def _company_warning(self, msg): action = self.env.ref('base.action_res_company_form') raise RedirectWarning(msg, action.id, _('Go to company configuration screen'))
def action_move_create(self): purchase_id = -1 letter_of_credit = -1 purchase_order = self.env['purchase.order'].search([]) for pick in purchase_order: if pick.invoice_ids: for inv_id in pick.invoice_ids: if inv_id.id == self.id: purchase_id = pick.id if pick.letter_of_credit.id: letter_of_credit = pick.letter_of_credit.id if letter_of_credit <= -1: return super(account_invoice, self).action_move_create() else: """ Creates invoice related analytics and financial move lines """ lc_liability_account = self.env['ir.values'].get_default('letter_of_credit.config.settings', 'lc_liability_account') account_move = self.env['account.move'] for inv in self: #lc_liability_account = inv.account_id.id if not inv.journal_id.sequence_id: raise UserError(_('Please define sequence on the journal related to this invoice.')) if not inv.invoice_line_ids: raise UserError(_('Please create some invoice lines.')) if inv.move_id: continue ctx = dict(self._context, lang=inv.partner_id.lang) if not inv.date_invoice: inv.with_context(ctx).write({'date_invoice': fields.Date.context_today(self)}) date_invoice = inv.date_invoice company_currency = inv.company_id.currency_id # create move lines (one per invoice line + eventual taxes and analytic lines) iml = inv.invoice_line_move_line_get() iml += inv.tax_line_move_line_get() diff_currency = inv.currency_id != company_currency # create one move line for the total and possibly adjust the other lines amount total, total_currency, iml = inv.with_context(ctx).compute_invoice_totals(company_currency, iml) name = inv.name or '/' if inv.payment_term_id: totlines = inv.with_context(ctx).payment_term_id.with_context(currency_id=inv.currency_id.id).compute(total, date_invoice)[0] res_amount_currency = total_currency ctx['date'] = date_invoice for i, t in enumerate(totlines): if inv.currency_id != company_currency: amount_currency = company_currency.with_context(ctx).compute(t[1], inv.currency_id) else: amount_currency = False # last line: add the diff res_amount_currency -= amount_currency or 0 if i + 1 == len(totlines): amount_currency += res_amount_currency iml.append({ 'type': 'dest', 'name': name, 'price': t[1], 'account_id': lc_liability_account, 'date_maturity': t[0], 'amount_currency': diff_currency and amount_currency, 'currency_id': diff_currency and inv.currency_id.id, 'invoice_id': inv.id }) else: iml.append({ 'type': 'dest', 'name': name, 'price': total, 'account_id': lc_liability_account, 'date_maturity': inv.date_due, 'amount_currency': diff_currency and total_currency, 'currency_id': diff_currency and inv.currency_id.id, 'invoice_id': inv.id }) part = self.env['res.partner']._find_accounting_partner(inv.partner_id) line = [(0, 0, self.line_get_convert(l, part.id)) for l in iml] line = inv.group_lines(iml, line) journal = inv.journal_id.with_context(ctx) line = inv.finalize_invoice_move_lines(line) date = inv.date or date_invoice move_vals = { 'ref': inv.reference, 'line_ids': line, 'journal_id': journal.id, 'date': date, 'narration': inv.comment, } ctx['company_id'] = inv.company_id.id ctx['dont_create_taxes'] = True ctx['invoice'] = inv ctx_nolang = ctx.copy() ctx_nolang.pop('lang', None) move = account_move.with_context(ctx_nolang).create(move_vals) # Pass invoice in context in method post: used if you want to get the same # account move reference when creating the same invoice after a cancelled one: move.post() # make the invoice point to that move vals = { 'move_id': move.id, 'date': date, 'move_name': move.name, } inv.with_context(ctx).write(vals) return True
def get_updated_currency(self, currency_array, main_currency, max_delta_days): """implementation of abstract method of Curreny_getter_interface""" # as of Jan 2014 BOC is publishing noon rates for about 60 currencies url = ('http://www.bankofcanada.ca/stats/assets/' 'rates_rss/noon/en_%s.xml') # closing rates are available as well (please note there are only 12 # currencies reported): # http://www.bankofcanada.ca/stats/assets/rates_rss/closing/en_%s.xml # We do not want to update the main currency if main_currency in currency_array: currency_array.remove(main_currency) import feedparser import pytz from dateutil import parser for curr in currency_array: _logger.debug("BOC currency rate service : connecting...") dom = feedparser.parse(url % curr) self.validate_cur(curr) # check if BOC service is running if dom.bozo and dom.status != 404: _logger.error("Bank of Canada - service is down - try again\ later...") # check if BOC sent a valid response for this currency if dom.status != 200: _logger.error("Exchange data for %s is not reported by Bank\ of Canada." % curr) raise except_orm( _('Error !'), _('Exchange data for %s is not ' 'reported by Bank of Canada.' % str(curr))) _logger.debug("BOC sent a valid RSS file for: " + curr) # check for valid exchange data if (dom.entries[0].cb_basecurrency == main_currency) and \ (dom.entries[0].cb_targetcurrency == curr): rate = dom.entries[0].cb_exchangerate.split('\n', 1)[0] rate_date_datetime = parser.parse(dom.entries[0].updated)\ .astimezone(pytz.utc).replace(tzinfo=None) self.check_rate_date(rate_date_datetime, max_delta_days) self.updated_currency[curr] = rate _logger.debug("BOC Rate retrieved : %s = %s %s" % (main_currency, rate, curr)) else: _logger.error("Exchange data format error for Bank of Canada -" "%s. Please check provider data format " "and/or source code." % curr) raise except_orm( _('Error !'), _('Exchange data format error for ' 'Bank of Canada - %s !' % str(curr))) return self.updated_currency, self.log_info
def _search_has_moves(self, operator, value): if operator != '=' or not value: raise ValueError(_("Unsupported search operator")) ids_with_moves = self._account_tax_ids_with_moves() return [('id', 'in', ids_with_moves)]
def product_id_change(self, product, uom_id, qty=0, name='', type='out_invoice', partner_id=False, fposition_id=False, price_unit=False, currency_id=False, company_id=None): context = self._context company_id = company_id if company_id is not None else context.get( 'company_id', False) company = self.env['res.company'].browse(company_id) self = self.with_context(company_id=company_id, force_company=company_id) if not partner_id: raise except_orm(_('No Partner Defined!'), _("You must first select a partner!")) if not product: if type in ('in_invoice', 'in_refund'): return {'value': {}, 'domain': {'uos_id': []}} else: return {'value': {'price_unit': 0.0}, 'domain': {'uos_id': []}} values = {} part = self.env['res.partner'].browse(partner_id) fpos = self.env['account.fiscal.position'].browse(fposition_id) if part.lang: self = self.with_context(lang=part.lang) product = self.env['product.product'].browse(product) values['name'] = product.partner_ref if type in ('out_invoice', 'out_refund'): account = product.property_account_income or product.categ_id.property_account_income_categ or company.property_account_income else: account = product.property_account_expense or product.categ_id.property_account_expense_categ or company.property_account_expense account = fpos.map_account(account) if account: values['account_id'] = account.id if type in ('out_invoice', 'out_refund'): taxes = product.taxes_id or account.tax_ids if product.description_sale: values['name'] += '\n' + product.description_sale else: taxes = product.supplier_taxes_id or account.tax_ids if product.description_purchase: values['name'] += '\n' + product.description_purchase fp_taxes = fpos.map_tax(taxes) values['invoice_line_tax_id'] = fp_taxes.ids if type in ('in_invoice', 'in_refund'): if price_unit and price_unit != product.standard_price: values['price_unit'] = price_unit else: values['price_unit'] = self.env[ 'account.tax']._fix_tax_included_price( product.standard_price, taxes, fp_taxes.ids) else: values['price_unit'] = self.env[ 'account.tax']._fix_tax_included_price(product.lst_price, taxes, fp_taxes.ids) values['uos_id'] = product.uom_id.id if uom_id: uom = self.env['product.uom'].browse(uom_id) if product.uom_id.category_id.id == uom.category_id.id: values['uos_id'] = uom_id domain = { 'uos_id': [('category_id', '=', product.uom_id.category_id.id)] } company = self.env['res.company'].browse(company_id) currency = self.env['res.currency'].browse(currency_id) if company and currency: if company.currency_id != currency: values['price_unit'] = values['price_unit'] * currency.rate if values['uos_id'] and values['uos_id'] != product.uom_id.id: values['price_unit'] = self.env['product.uom']._compute_price( product.uom_id.id, values['price_unit'], values['uos_id']) return {'value': values, 'domain': domain}
def create_employee_from_applicant(self): """ Create an hr.employee from the hr.applicants """ check_dup = self.check_duplicate_employee() if not check_dup: employee = False for applicant in self: address_id = contact_name = False if applicant.partner_id: address_id = applicant.partner_id.address_get( ['contact'])['contact'] contact_name = applicant.partner_id.name_get()[0][1] if applicant.job_id and (applicant.partner_name or contact_name): applicant.job_id.write({ 'no_of_hired_employee': applicant.job_id.no_of_hired_employee + 1 }) employee = self.env['hr.employee'].create({ 'name': applicant.partner_name or contact_name, 'job_id': applicant.job_id.id, 'address_home_id': address_id, 'department_id': applicant.department_id.id or False, 'address_id': applicant.company_id and applicant.company_id.partner_id and applicant.company_id.partner_id.id or False, 'work_email': applicant.department_id and applicant.department_id.company_id and applicant.department_id.company_id.email or False, 'work_phone': applicant.department_id and applicant.department_id.company_id and applicant.department_id.company_id.phone or False, 'identification_id': applicant.identification_id or False, 'insurance_number': applicant.insurance_number or False, 'tin': applicant.tin or False, }) applicant.write({'emp_id': employee.id}) applicant.job_id.message_post( body=_('New Employee %s Hired') % applicant.partner_name if applicant.partner_name else applicant.name, subtype="hr_recruitment.mt_job_applicant_hired") employee._broadcast_welcome() else: raise UserError( _('You must define an Applied Job and a Contact Name for this applicant.' )) employee_action = self.env.ref('hr.open_view_employee_list') dict_act_window = employee_action.read([])[0] if employee: dict_act_window['res_id'] = employee.id dict_act_window['view_mode'] = 'form,tree' return dict_act_window
def unlink(self): if self.state != 'draft': raise UserError( _('It is forbidden to modify a distribution list which is not in draft status' )) super(DeliveryDistributionLine, self).unlink()