You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

206 lines
9.4 KiB
Python

8 months ago
# -*- coding: utf-8 -*-
# &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
# QQ:570165989
# Author'wangshuai'
# Date2020/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
#