diff --git a/fusion-plating/fusion_plating_invoicing/__init__.py b/fusion-plating/fusion_plating_invoicing/__init__.py new file mode 100644 index 00000000..3c90fa80 --- /dev/null +++ b/fusion-plating/fusion_plating_invoicing/__init__.py @@ -0,0 +1,6 @@ +# -*- coding: utf-8 -*- +# Copyright 2026 Nexa Systems Inc. +# License OPL-1 (Odoo Proprietary License v1.0) +# Part of the Fusion Plating product family. + +from . import models diff --git a/fusion-plating/fusion_plating_invoicing/__manifest__.py b/fusion-plating/fusion_plating_invoicing/__manifest__.py new file mode 100644 index 00000000..233d44b1 --- /dev/null +++ b/fusion-plating/fusion_plating_invoicing/__manifest__.py @@ -0,0 +1,46 @@ +# -*- coding: utf-8 -*- +# Copyright 2026 Nexa Systems Inc. +# License OPL-1 (Odoo Proprietary License v1.0) +# Part of the Fusion Plating product family. + +{ + 'name': 'Fusion Plating — Invoicing', + 'version': '19.0.1.0.0', + 'category': 'Manufacturing/Plating', + 'summary': 'Invoice strategy engine with deposit, progress billing, net terms, COD/prepay, and account holds.', + 'description': """ +Fusion Plating — Invoicing +=========================== + +Part of the Fusion Plating product family by Nexa Systems Inc. + +Provides: +- Four invoice strategies: deposit, progress billing, net terms, COD/prepay +- Customer-level default strategy with auto-fill on sale orders +- Account hold flag on customers to block SO confirmation and invoicing +- Automated deposit and full invoice creation on SO confirmation +""", + 'author': 'Nexa Systems Inc.', + 'website': 'https://www.nexasystems.ca', + 'maintainer': 'Nexa Systems Inc.', + 'support': 'support@nexasystems.ca', + 'license': 'OPL-1', + 'price': 0.00, + 'currency': 'CAD', + 'depends': [ + 'fusion_plating_configurator', + 'sale_management', + 'account', + ], + 'data': [ + 'security/fp_invoicing_security.xml', + 'security/ir.model.access.csv', + 'views/fp_invoice_strategy_views.xml', + 'views/res_partner_views.xml', + 'views/sale_order_views.xml', + 'views/fp_invoicing_menu.xml', + ], + 'installable': True, + 'application': False, + 'auto_install': False, +} diff --git a/fusion-plating/fusion_plating_invoicing/models/__init__.py b/fusion-plating/fusion_plating_invoicing/models/__init__.py new file mode 100644 index 00000000..ec78ddf6 --- /dev/null +++ b/fusion-plating/fusion_plating_invoicing/models/__init__.py @@ -0,0 +1,9 @@ +# -*- coding: utf-8 -*- +# Copyright 2026 Nexa Systems Inc. +# License OPL-1 (Odoo Proprietary License v1.0) +# Part of the Fusion Plating product family. + +from . import fp_invoice_strategy_default +from . import res_partner +from . import sale_order +from . import account_move diff --git a/fusion-plating/fusion_plating_invoicing/models/account_move.py b/fusion-plating/fusion_plating_invoicing/models/account_move.py new file mode 100644 index 00000000..0c8fe912 --- /dev/null +++ b/fusion-plating/fusion_plating_invoicing/models/account_move.py @@ -0,0 +1,5 @@ +# -*- coding: utf-8 -*- +# Copyright 2026 Nexa Systems Inc. +# License OPL-1 (Odoo Proprietary License v1.0) +# Part of the Fusion Plating product family. +# Placeholder — implemented in a later task. diff --git a/fusion-plating/fusion_plating_invoicing/models/fp_invoice_strategy_default.py b/fusion-plating/fusion_plating_invoicing/models/fp_invoice_strategy_default.py new file mode 100644 index 00000000..7bb1ddb7 --- /dev/null +++ b/fusion-plating/fusion_plating_invoicing/models/fp_invoice_strategy_default.py @@ -0,0 +1,39 @@ +# -*- coding: utf-8 -*- +# Copyright 2026 Nexa Systems Inc. +# License OPL-1 (Odoo Proprietary License v1.0) +# Part of the Fusion Plating product family. + +from odoo import fields, models + + +class FpInvoiceStrategyDefault(models.Model): + """Customer-level default invoice strategy. + + When a new sale order is created for this customer, the invoice + strategy and deposit percentage auto-fill from this record. + """ + _name = 'fp.invoice.strategy.default' + _description = 'Fusion Plating — Invoice Strategy Default' + _order = 'partner_id' + + partner_id = fields.Many2one( + 'res.partner', string='Customer', required=True, ondelete='cascade', + domain="[('customer_rank', '>', 0)]", + ) + default_strategy = fields.Selection( + [('deposit', 'Deposit'), ('progress', 'Progress Billing'), + ('net_terms', 'Net Terms'), ('cod_prepay', 'COD / Prepay')], + string='Default Strategy', required=True, + ) + default_deposit_percent = fields.Float( + string='Deposit %', help='Deposit percentage if strategy is Deposit (e.g. 50.0).', + ) + payment_term_id = fields.Many2one( + 'account.payment.term', string='Payment Terms', + ) + notes = fields.Text(string='Notes') + + _sql_constraints = [ + ('fp_invoice_strategy_partner_uniq', 'unique(partner_id)', + 'Only one invoice strategy default per customer.'), + ] diff --git a/fusion-plating/fusion_plating_invoicing/models/res_partner.py b/fusion-plating/fusion_plating_invoicing/models/res_partner.py new file mode 100644 index 00000000..a44206d2 --- /dev/null +++ b/fusion-plating/fusion_plating_invoicing/models/res_partner.py @@ -0,0 +1,22 @@ +# -*- coding: utf-8 -*- +# Copyright 2026 Nexa Systems Inc. +# License OPL-1 (Odoo Proprietary License v1.0) +# Part of the Fusion Plating product family. + +from odoo import fields, models + + +class ResPartner(models.Model): + _inherit = 'res.partner' + + x_fc_account_hold = fields.Boolean( + string='Account Hold', tracking=True, + help='When active, blocks SO confirmation, invoicing, and shipping.', + ) + x_fc_account_hold_reason = fields.Text(string='Hold Reason') + x_fc_account_hold_date = fields.Datetime( + string='Hold Date', help='When the hold was placed.', + ) + x_fc_account_hold_by_id = fields.Many2one( + 'res.users', string='Hold Placed By', + ) diff --git a/fusion-plating/fusion_plating_invoicing/models/sale_order.py b/fusion-plating/fusion_plating_invoicing/models/sale_order.py new file mode 100644 index 00000000..0c8fe912 --- /dev/null +++ b/fusion-plating/fusion_plating_invoicing/models/sale_order.py @@ -0,0 +1,5 @@ +# -*- coding: utf-8 -*- +# Copyright 2026 Nexa Systems Inc. +# License OPL-1 (Odoo Proprietary License v1.0) +# Part of the Fusion Plating product family. +# Placeholder — implemented in a later task. diff --git a/fusion-plating/fusion_plating_invoicing/security/fp_invoicing_security.xml b/fusion-plating/fusion_plating_invoicing/security/fp_invoicing_security.xml new file mode 100644 index 00000000..f9c60e95 --- /dev/null +++ b/fusion-plating/fusion_plating_invoicing/security/fp_invoicing_security.xml @@ -0,0 +1,17 @@ + + + + + + Accounting + 58 + + + + + + diff --git a/fusion-plating/fusion_plating_invoicing/security/ir.model.access.csv b/fusion-plating/fusion_plating_invoicing/security/ir.model.access.csv new file mode 100644 index 00000000..6195f58a --- /dev/null +++ b/fusion-plating/fusion_plating_invoicing/security/ir.model.access.csv @@ -0,0 +1,4 @@ +id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink +access_fp_invoice_strategy_operator,fp.invoice.strategy.default.operator,model_fp_invoice_strategy_default,fusion_plating.group_fusion_plating_operator,1,0,0,0 +access_fp_invoice_strategy_accounting,fp.invoice.strategy.default.accounting,model_fp_invoice_strategy_default,group_fp_accounting,1,1,1,0 +access_fp_invoice_strategy_manager,fp.invoice.strategy.default.manager,model_fp_invoice_strategy_default,fusion_plating.group_fusion_plating_manager,1,1,1,1 diff --git a/fusion-plating/fusion_plating_invoicing/static/description/icon.png b/fusion-plating/fusion_plating_invoicing/static/description/icon.png new file mode 100644 index 00000000..a61b43b7 Binary files /dev/null and b/fusion-plating/fusion_plating_invoicing/static/description/icon.png differ diff --git a/fusion-plating/fusion_plating_invoicing/views/fp_invoice_strategy_views.xml b/fusion-plating/fusion_plating_invoicing/views/fp_invoice_strategy_views.xml new file mode 100644 index 00000000..e12f4390 --- /dev/null +++ b/fusion-plating/fusion_plating_invoicing/views/fp_invoice_strategy_views.xml @@ -0,0 +1,85 @@ + + + + + + + fp.invoice.strategy.default.list + fp.invoice.strategy.default + + + + + + + + + + + + + fp.invoice.strategy.default.form + fp.invoice.strategy.default + + + + + + + + + + + + + + + + + + + + + + + + fp.invoice.strategy.default.search + fp.invoice.strategy.default + + + + + + + + + + + + + + + + + + Invoice Strategy Defaults + fp.invoice.strategy.default + list,form + + + + No invoice strategy defaults defined yet + + + Set a default invoice strategy per customer so new sale orders + auto-fill with the correct billing method. + + + + + diff --git a/fusion-plating/fusion_plating_invoicing/views/fp_invoicing_menu.xml b/fusion-plating/fusion_plating_invoicing/views/fp_invoicing_menu.xml new file mode 100644 index 00000000..3859f8d4 --- /dev/null +++ b/fusion-plating/fusion_plating_invoicing/views/fp_invoicing_menu.xml @@ -0,0 +1,8 @@ + + + + diff --git a/fusion-plating/fusion_plating_invoicing/views/res_partner_views.xml b/fusion-plating/fusion_plating_invoicing/views/res_partner_views.xml new file mode 100644 index 00000000..40b332fb --- /dev/null +++ b/fusion-plating/fusion_plating_invoicing/views/res_partner_views.xml @@ -0,0 +1,47 @@ + + + + + + res.partner.form.fp.account.hold + res.partner + + + + + Account Hold Active — + + + + Placed by + on + + + + + + + + + + + + + + + + + + + + + diff --git a/fusion-plating/fusion_plating_invoicing/views/sale_order_views.xml b/fusion-plating/fusion_plating_invoicing/views/sale_order_views.xml new file mode 100644 index 00000000..3859f8d4 --- /dev/null +++ b/fusion-plating/fusion_plating_invoicing/views/sale_order_views.xml @@ -0,0 +1,8 @@ + + + +
+ No invoice strategy defaults defined yet +
+ Set a default invoice strategy per customer so new sale orders + auto-fill with the correct billing method. +