# -*- coding: utf-8 -*- # &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& # QQ:570165989 # Author:'wangshuai' # Date:2020/11/25 0025 # &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& import datetime from datetime import date from odoo import models, fields, api, _ from odoo.exceptions import ValidationError, MissingError, UserError class AccountMove(models.Model): _inherit = 'account.move' _description = '记账凭证' journal_id = fields.Many2one( 'account.journal', string='Journal', compute='_compute_journal_id', store=True, readonly=False, precompute=True, required=True, states={'draft': [('readonly', False)]}, check_company=True, domain="[('id', 'in', suitable_journal_ids)]", ) @api.depends('company_id', 'invoice_filter_type_domain') def _compute_suitable_journal_ids(self): for m in self: # journal_type = m.invoice_filter_type_domain or 'general' company_id = m.company_id.id or self.env.company.id domain = [('company_id', '=', company_id)] m.suitable_journal_ids = self.env['account.journal'].search(domain) @api.constrains('name', 'journal_id', 'state') def _check_unique_sequence_number(self): moves = self.filtered(lambda move: move.state == 'posted') if not moves: return # self.flush(['name', 'journal_id', 'move_type', 'state']) self.flush_model(['name', 'journal_id', 'move_type', 'state']) # /!\ Computed stored fields are not yet inside the database. self._cr.execute(''' SELECT move2.id, move2.name FROM account_move move INNER JOIN account_move move2 ON move2.name = move.name AND move2.journal_id = move.journal_id AND move2.move_type = move.move_type AND move2.id != move.id WHERE move.id IN %s AND move2.state = 'posted' ''', [tuple(moves.ids)]) res = self._cr.fetchall() if res: for order in self: # 查询系统编号 sequence_name = self.env['ir.sequence'].search([('code', '=', 'move.sequence.constant'), ('company_id', '=', self.company_id.id)]) # 该公司无系统编号则创建 if not sequence_name: sequence_name = self.env['ir.sequence'].create({ 'name': '%s凭证序列(固定)' % order.company_id.name, 'code': 'move.sequence.constant', 'implementation': 'no_gap', 'padding': 4, 'prefix': '%(range_year)s/%(range_month)s/', 'use_date_range': True, 'date_range_type': 'month', 'company_id': order.company_id.id, }) # 如果查询到,编号有误。那么自动获取最重排编号。 all_move = self.env['account.move'].search([('company_id', '=', self.company_id.id), ('fr_period_id', '=', self.fr_period_id.id)]) self.name = sequence_name.with_context(ir_sequence_date=self.date).next_by_id() # self._generate_move_name_next(all_move, sequence_name) # 此方法注释掉。报错提示。直接重新生成新的系统编号 # raise ValidationError(_('Posted journal entry must have an unique sequence number per company.\n' # 'Problematic numbers: %s\n') % ', '.join(r[1] for r in res)) # 手动删除6月份,凭证明细行的,现金流量项目 def clean_line_fr_cash_flow_id(self): account_move_line = self.env['account.move.line'].search([('fr_period_id', '=', 6)]) for line in account_move_line: if line.account_id.user_type_id.name != '银行和现金': line.fr_cash_flow_id = None # 去除,删除,非银行科目,现金流量项目 def clean_line_fr_cash_flow(self): account_move_line = self.env['account.move.line'].search([]) for line in account_move_line: if line.account_id.user_type_id.name != '银行和现金': line.fr_cash_flow_id = None # 审批已完成的结算单,修改状态为已取消。目的:为了能删除 def cancel_passed_approval(self): ai = self.env['approval.flow.instance'].search([('res_id', '=', self.id), ('model_name', '=', 'account.move')]) ai[0].state = 'cancel' # 好。 def action_add_quick(self): """ 快捷添加分析账户分析标签按钮 :return: """ self.ensure_one() return { 'type': 'ir.actions.act_window', 'res_model': 'quick.add.wizard', 'view_mode': 'form', 'view_type': 'form', 'views': [[self.env.ref('account_ledger.QuickAddWizardViewForm').id, 'form']], 'context': { 'default_account_move_id': self.id, }, 'name': '快捷添加分析账户、分析标签', 'target': 'new' } # 会计发票,确认操作时,添加 凭证 审核人 ,审核日期 过账人,过账日期 def action_post(self): res = super(AccountMove, self).action_post() self.write({ 'fr_approved_uid': self.env.user.id, 'fr_approved_date': datetime.datetime.now(), 'fr_posted_uid': self.env.user.id, 'fr_posted_date': datetime.datetime.now(), }) # 检查分析标签-分析账户必填 for order in self: for line in order.line_ids: if line.account_id.cash_bool: if len(line.fr_cash_flow_id) <= 0: raise ValidationError('会计分录,账户:【' + line.account_id.name + '】没有选择现金流量,请选择后重试' + str(order)) if line.account_id.label_bool: if len(line.analytic_tag_ids) <= 0: raise ValidationError('对应科目分析标签/账户必填,请点击【快捷添加标签/账户】按钮,快捷添加!记录ID:' + str(order)) if line.account_id.analysis_bool: if len(line.analytic_account_id) <= 0: raise ValidationError('对应科目分析标签/账户必填,请点击【快捷添加标签/账户】按钮,快捷添加!记录ID:' + str(order)) # 发票点击确认 - 检查科目 相关业务伙伴是否 勾选必填。 # for order in self: # for line in order.line_ids: # if line.account_id.partner_bool: # line.write({ # 'partner_id': order.partner_id.id, # }) # else: # line.write({ # 'partner_id': None, # }) # # # 如果科目中没有选择 标签和账户,那么将标签和账户 设置为空 # if not line.account_id.analysis_bool: # line.write({ # 'analytic_account_id': None, # }) # if not line.account_id.label_bool: # line.write({ # 'analytic_tag_ids': None, # }) return res # 重写并修改从销售发货过来生成的库存相关凭证方法 def _post(self, soft=True): posted = super()._post(soft) self.write({ 'fr_approved_uid': self.env.user.id, 'fr_approved_date': datetime.datetime.now(), 'fr_posted_uid': self.env.user.id, 'fr_posted_date': datetime.datetime.now(), }) # - 检查科目 相关业务伙伴是否 勾选必填。系统原生逻辑是将业务伙伴加上。实际是根据我们后台配置进行修改。科目上配置了 # - 那么就添加,未配置。就不添加 # for order in self: # for line in order.line_ids: # if line.account_id.partner_bool: # line.write({ # 'partner_id': order.partner_id.id, # }) # else: # line.write({ # 'partner_id': None, # }) return posted # 会计发票,重置为草稿状态 不允许非当前会计期间单据重置为草稿操作 def button_draft(self): res = super(AccountMove, self).button_draft() # if self.fr_period_state != 'ongoing': # raise UserError(_("当前单据对应的凭证的会计期间已关闭。不允许进行重置操作。")) # 重置为草稿 、将审核人、审核日期 、 过账人、过账日期 清楚。 self.write({ 'fr_posted_uid': None, 'fr_posted_date': None, 'fr_approved_uid': None, 'fr_approved_date': None, }) return res #