写点什么

Odoo 发票管理增强套件 - 全面提升企业开票效率

作者:qife122
  • 2025-10-08
    福建
  • 本文字数:3372 字

    阅读完需:约 11 分钟

Odoo 发票管理增强套件

项目描述

account-invoicing 是一个专为 Odoo 企业资源规划系统设计的发票管理增强套件。该项目包含多个功能模块,全面覆盖发票处理的各个环节,从创建、折扣计算、发送到后期管理,为企业提供完整的发票解决方案。所有模块均基于 Odoo Community Association (OCA)开发,确保代码质量和兼容性。

功能特性

核心功能模块

  • 全局折扣管理 - 支持在发票级别应用全局折扣,自动计算折扣金额并更新相关会计科目

  • 自动邮件发送 - 对配置为邮件传输方式的发票自动发送,支持队列作业处理

  • 到期日期编辑 - 允许在发票过账后编辑到期日期,增强灵活性

  • 税种强制检查 - 确保每张发票行都设置了正确的税种,避免税务错误

  • 供应商信息更新 - 自动检测并更新产品供应商信息,保持采购数据同步

  • 退款原因管理 - 为贷项通知单定义标准化的退款原因,便于统计分析

  • 多销售订单分组 - 在合并开票时按销售订单分组显示,提高可读性

  • 汇率显示 - 清晰展示发票使用的货币汇率,支持多币种环境

  • 供应商发票号唯一性检查 - 防止重复录入供应商发票,避免重复付款风险

技术特色

  • 完整的权限控制体系,确保数据安全

  • 支持预初始化钩子和后初始化钩子

  • 与 Odoo 标准模块无缝集成

  • 多公司、多币种支持

  • 响应式设计,适配各种设备

安装指南

系统要求

  • Odoo 18.0 或更高版本

  • Python 3.7+

  • PostgreSQL 9.6+

安装步骤

  1. 将项目克隆到 Odoo 的 addons 目录:


cd /path/to/odoo/addonsgit clone https://github.com/OCA/account-invoicing.git
复制代码


  1. 在 Odoo 中安装所需模块:


# 安装全局折扣模块module install account_global_discount
# 安装自动邮件发送模块 module install account_invoice_auto_send_by_email
# 安装其他需要的模块...
复制代码


  1. 配置依赖项:各模块的依赖关系已在 manifest 文件中定义,Odoo 会自动处理。

平台注意事项

  • 所有模块均支持 Linux、Windows 和 macOS 平台

  • 建议在生产环境使用前在测试环境充分验证

  • 确保有足够的数据库权限执行表结构变更

使用说明

全局折扣配置

  1. 进入 设置 > 参数 > 全局折扣

  2. 添加新的折扣百分比

  3. 选择折扣适用范围(销售或采购)

  4. 可限制特定公司使用


# 为合作伙伴设置全局折扣示例partner_id = self.env['res.partner'].browse(partner_id)partner_id.customer_global_discount_ids = [(6, 0, [discount_id])]
复制代码

自动邮件发送

配置传输方法为邮件的发票会自动加入发送队列:


# 检查待发送的发票invoices = self.env['account.move'].search([    ('transmit_method_id', '=', email_method_id),    ('state', '=', 'posted'),    ('is_move_sent', '=', False)])
复制代码

到期日期管理

启用到期日期编辑功能:


<!-- 安全组配置 --><record id="group_account_invoice_date_due" model="res.groups">    <field name="name">Allow to change due date</field></record>
复制代码

供应商信息更新

在供应商发票中检查和更新产品信息:


def update_supplierinfo(self):    """更新产品供应商信息"""    for line in self.line_ids:        if not line.supplierinfo_id:            # 创建新的供应商信息            vals = line._prepare_supplierinfo()            self.env['product.supplierinfo'].create(vals)        else:            # 更新现有供应商信息            vals = line._prepare_supplierinfo_update()            line.supplierinfo_id.write(vals)
复制代码

核心代码

全局折扣预初始化

def _pre_init_global_discount_fields(env):    """预初始化全局折扣字段"""    if not column_exists(env.cr, "account_move", "amount_global_discount"):        env.cr.execute("""            ALTER TABLE "account_move"            ADD COLUMN "amount_global_discount" double precision DEFAULT 0        """)        env.cr.execute("""            ALTER TABLE "account_move" ALTER COLUMN "amount_global_discount" DROP DEFAULT        """)        # 初始化税前金额字段    if not column_exists(env.cr, "account_move", "amount_untaxed_before_global_discounts"):        env.cr.execute("""            ALTER TABLE "account_move"            ADD COLUMN "amount_untaxed_before_global_discounts" double precision        """)        env.cr.execute("""            update account_move set amount_untaxed_before_global_discounts = amount_untaxed        """)
复制代码

退款原因管理

class AccountMoveReversal(models.TransientModel):    _inherit = "account.move.reversal"
reason_id = fields.Many2one("account.move.refund.reason", string="退款原因") reason = fields.Char( compute="_compute_reason", precompute=True, store=True, readonly=False )
@api.depends("reason_id") def _compute_reason(self): """计算退款原因""" for record in self: if record.reason_id: record.reason = record.reason_id.name
def reverse_moves(self, is_modify=False): """重写退款创建方法,设置原因字段""" res = super().reverse_moves(is_modify=is_modify) # 为新创建的退款设置原因 self.move_ids.reversal_move_ids.filtered(lambda x: not x.reason_id).write( {"reason_id": self.reason_id.id} ) return res
复制代码

供应商信息更新向导

class WizardUpdateInvoiceSupplierinfo(models.TransientModel):    _name = "wizard.update.invoice.supplierinfo"    _description = "更新供应商信息向导"
line_ids = fields.One2many( comodel_name="wizard.update.invoice.supplierinfo.line", inverse_name="wizard_id", string="明细行", ) invoice_id = fields.Many2one( comodel_name="account.move", required=True, readonly=True, ondelete="cascade", )
def update_supplierinfo(self): """执行供应商信息更新""" self.ensure_one() supplierinfo_obj = self.env["product.supplierinfo"] for line in self.line_ids: supplierinfo = line.supplierinfo_id if not supplierinfo: # 创建新的供应商信息记录 vals = line._prepare_supplierinfo() supplierinfo_obj.create(vals) else: # 更新现有供应商信息 vals = line._prepare_supplierinfo_update() supplierinfo.write(vals) # 更新产品的采购单位 if ("product_uom" in vals and vals["product_uom"] != line.product_id.uom_po_id.id): line.product_id.uom_po_id = vals["product_uom"]
# 标记发票为已检查 self.invoice_id.write({"supplierinfo_ok": True})
复制代码

发票行与原始行匹配

def match_origin_lines(refund):    """通过产品或描述匹配退款行与原始发票行"""    invoice = refund.reversed_entry_id    invoice_lines = invoice.invoice_line_ids    for refund_line in refund.invoice_line_ids:        for invoice_line in invoice_lines:            # 通过产品或名称匹配            match = (                refund_line.product_id                and refund_line.product_id == invoice_line.product_id                or refund_line.name == invoice_line.name            )            if match:                invoice_lines -= invoice_line                refund_line.origin_line_id = invoice_line.id                break        if not invoice_lines:            break
复制代码


这些核心代码展示了项目的技术实现,包括数据库操作、业务逻辑处理和用户交互设计,体现了代码的专业性和可维护性。更多精彩内容 请关注我的个人公众号 公众号(办公 AI 智能小助手)对网络安全、黑客技术感兴趣的朋友可以关注我的安全公众号(网络安全技术点滴分享)


公众号二维码


办公AI智能小助手


公众号二维码


网络安全技术点滴分享


用户头像

qife122

关注

还未添加个人签名 2021-05-19 加入

还未添加个人简介

评论

发布
暂无评论
Odoo发票管理增强套件 - 全面提升企业开票效率_Odoo_qife122_InfoQ写作社区