diff --git a/gn_discount/.gitignore b/gn_discount/.gitignore new file mode 100644 index 0000000..01067d3 --- /dev/null +++ b/gn_discount/.gitignore @@ -0,0 +1,2 @@ +__pycache__ +models/__pycache__ \ No newline at end of file diff --git a/gn_discount/__init__.py b/gn_discount/__init__.py new file mode 100644 index 0000000..5305644 --- /dev/null +++ b/gn_discount/__init__.py @@ -0,0 +1,3 @@ +# -*- coding: utf-8 -*- + +from . import models \ No newline at end of file diff --git a/gn_discount/__manifest__.py b/gn_discount/__manifest__.py new file mode 100644 index 0000000..362237e --- /dev/null +++ b/gn_discount/__manifest__.py @@ -0,0 +1,24 @@ +{ + 'name': "Gn Discount", + 'version': '14.0.0.1.3', + 'author': 'Garage Numérique', + 'category': 'Sales', + 'description': """ + This module adds the ability to display the total before discount and the discount amount on sales orders and invoices. + + This version only works when no taxes are applied + """, + 'depends': ['sale', 'sale_discount_total'], + 'data': [ + 'views/sale_view.xml', + 'views/sale_report.xml', + 'views/sale_portal.xml', + 'views/invoice_view.xml', + 'views/invoice_report.xml' + ], + 'translate': True, + 'translations': [ + ('fr_FR', 'i18n/gn_discount.fr_FR.po'), + ], + 'installable': True, +} diff --git a/gn_discount/i18n/gn_discount.fr_FR.po b/gn_discount/i18n/gn_discount.fr_FR.po new file mode 100644 index 0000000..2c603de --- /dev/null +++ b/gn_discount/i18n/gn_discount.fr_FR.po @@ -0,0 +1,14 @@ +msgid "Subtotal" +msgstr "Sous-total" + +msgid "Discount" +msgtr "Remise" + +msgid "Subtotal with discount" +msgtr "Sous-total après remise" + +msgid "Total without discount" +msgtr "Total avant remise" + +msgid "Total discounted" +msgtr "Total après remise" \ No newline at end of file diff --git a/gn_discount/models/__init__.py b/gn_discount/models/__init__.py new file mode 100644 index 0000000..3546aed --- /dev/null +++ b/gn_discount/models/__init__.py @@ -0,0 +1,3 @@ +# -*- coding: utf-8 -*- + +from . import sale, invoice \ No newline at end of file diff --git a/gn_discount/models/invoice.py b/gn_discount/models/invoice.py new file mode 100644 index 0000000..ac88bd8 --- /dev/null +++ b/gn_discount/models/invoice.py @@ -0,0 +1,19 @@ +from odoo import api, fields, models + +class AccountMove(models.Model): + _inherit = 'account.move' + amount_undiscounted = fields.Monetary(compute='_compute_amount_undiscounted', store=True) + + @api.depends('amount_untaxed', 'amount_discount') + def _compute_amount_undiscounted(self): + for record in self: + record.amount_undiscounted = record.amount_untaxed + record.amount_discount + +class AccountMoveLine(models.Model): + _inherit = 'account.move.line' + price_subtotal_before_discount = fields.Monetary(compute='_compute_amount_undiscounted', store=True, string="Subtotal", translate="True") + + @api.depends('price_unit', 'quantity') + def _compute_amount_undiscounted(self): + for record in self: + record.price_subtotal_before_discount = record.price_unit * record.quantity diff --git a/gn_discount/models/sale.py b/gn_discount/models/sale.py new file mode 100644 index 0000000..4d1091e --- /dev/null +++ b/gn_discount/models/sale.py @@ -0,0 +1,11 @@ +from odoo import api, fields, models + +class SaleOrderLine(models.Model): + _inherit = 'sale.order.line' + + price_subtotal_before_discount = fields.Monetary(readonly=True, string="Subtotal", translate=True, compute='_compute_price_subtotal_before_discount') + + @api.depends('price_unit', 'discount', 'product_uom_qty') + def _compute_price_subtotal_before_discount(self): + for line in self: + line.price_subtotal_before_discount = line.price_unit * line.product_uom_qty \ No newline at end of file diff --git a/gn_discount/views/invoice_report.xml b/gn_discount/views/invoice_report.xml new file mode 100644 index 0000000..be50d0b --- /dev/null +++ b/gn_discount/views/invoice_report.xml @@ -0,0 +1,64 @@ + + + + diff --git a/gn_discount/views/invoice_view.xml b/gn_discount/views/invoice_view.xml new file mode 100644 index 0000000..85e2356 --- /dev/null +++ b/gn_discount/views/invoice_view.xml @@ -0,0 +1,22 @@ + + + + + gn_discount.account.move.form + account.move + + + + + + + + + + + + + + + + diff --git a/gn_discount/views/sale_portal.xml b/gn_discount/views/sale_portal.xml new file mode 100644 index 0000000..58f4b67 --- /dev/null +++ b/gn_discount/views/sale_portal.xml @@ -0,0 +1,76 @@ + + + + + + + + \ No newline at end of file diff --git a/gn_discount/views/sale_report.xml b/gn_discount/views/sale_report.xml new file mode 100644 index 0000000..223d061 --- /dev/null +++ b/gn_discount/views/sale_report.xml @@ -0,0 +1,55 @@ + + + + \ No newline at end of file diff --git a/gn_discount/views/sale_view.xml b/gn_discount/views/sale_view.xml new file mode 100644 index 0000000..387abc9 --- /dev/null +++ b/gn_discount/views/sale_view.xml @@ -0,0 +1,22 @@ + + + + + gn_discount.sale.order.form + sale.order + + 99 + + + + + + + + + + + + + + diff --git a/gn_donations/.gitignore b/gn_donations/.gitignore new file mode 100644 index 0000000..01067d3 --- /dev/null +++ b/gn_donations/.gitignore @@ -0,0 +1,2 @@ +__pycache__ +models/__pycache__ \ No newline at end of file diff --git a/gn_donations/__init__.py b/gn_donations/__init__.py new file mode 100644 index 0000000..cde864b --- /dev/null +++ b/gn_donations/__init__.py @@ -0,0 +1,3 @@ +# -*- coding: utf-8 -*- + +from . import models diff --git a/gn_donations/__manifest__.py b/gn_donations/__manifest__.py new file mode 100644 index 0000000..959bf00 --- /dev/null +++ b/gn_donations/__manifest__.py @@ -0,0 +1,17 @@ +{ + 'name': "Gn Donations", + 'version': '14.0.0.1.1', + 'author': 'Garage Numérique', + 'category': 'Accounting', + 'description': """ + This module modify the fiscal receipt report so it is similar to Cerfa 11580. + It allows to edit fiscal receipts for in-kind donation (i.e. 0€ donation). + """, + 'depends': ['donation'], + 'data': [ + 'views/donation_thanks_report.xml', + 'views/internal_layout.xml' + ], + 'translate': True, + 'installable': True, +} diff --git a/gn_donations/models/__init__.py b/gn_donations/models/__init__.py new file mode 100644 index 0000000..cea6262 --- /dev/null +++ b/gn_donations/models/__init__.py @@ -0,0 +1,3 @@ +# -*- coding: utf-8 -*- + +from . import donation diff --git a/gn_donations/models/donation.py b/gn_donations/models/donation.py new file mode 100644 index 0000000..71eac46 --- /dev/null +++ b/gn_donations/models/donation.py @@ -0,0 +1,127 @@ +# -*- coding: utf-8 -*- +from odoo import fields, models +import num2words + +class TaxReceipt(models.Model): + _inherit = 'donation.tax.receipt' + amount_in_words = fields.Char(compute='_compute_amount_in_words', string='Amount in Words') + + def _compute_amount_in_words(self): + for record in self: + record.amount_in_words = num2words.num2words(record.amount, lang='fr') + + +from odoo import _, api +from odoo.exceptions import UserError +from odoo.tools.misc import format_amount + +from odoo.addons.account import _auto_install_l10n +# Rewriting donation to allow 0€ fiscal receipts +class DonationDonation(models.Model): + _inherit = 'donation.donation' + + def validate(self): + check_total = self.env["res.users"].has_group( + "donation.group_donation_check_total" + ) + for donation in self: + if donation.donation_date > fields.Date.context_today(self): + raise UserError( + _( + "The date of donation %s should be today " + "or in the past, not in the future!" + ) + % donation.number + ) + if not donation.line_ids: + raise UserError( + _( + "Cannot validate donation %s because it doesn't " + "have any lines!" + ) + % donation.number + ) + + ''' + # The part we don't want, in order ta validate 0€ fiscal receipts + if donation.currency_id.is_zero(donation.amount_total): + raise UserError( + _("Cannot validate donation %s because the " "total amount is 0!") + % donation.number + ) + ''' + + if donation.state != "draft": + raise UserError( + _( + "Cannot validate donation %s because it is not " + "in draft state." + ) + % donation.number + ) + + if check_total and donation.currency_id.compare_amounts( + donation.check_total, donation.amount_total + ): + raise UserError( + _( + "The amount of donation %s (%s) is different " + "from the sum of the donation lines (%s)." + ) + % ( + donation.number, + format_amount( + self.env, donation.check_total, donation.currency_id + ), + format_amount( + self.env, donation.amount_total, donation.currency_id + ), + ) + ) + full_in_kind = all([line.in_kind for line in donation.line_ids]) + if not donation.payment_mode_id and not full_in_kind: + raise UserError( + _( + "Payment Mode is not set on donation %s (only fully " + "in-kind donations don't require a payment mode)." + ) + % donation.number + ) + + vals = {"state": "done"} + if full_in_kind and donation.payment_mode_id: + vals["payment_mode_id"] = False + + if not full_in_kind: + move_vals = donation._prepare_donation_move() + # when we have a full in-kind donation: no account move + if move_vals: + move = self.env["account.move"].create(move_vals) + move.action_post() + vals["move_id"] = move.id + else: + donation.message_post( + body=_("Full in-kind donation: no account move generated") + ) + + receipt = donation.generate_each_tax_receipt() + if receipt: + vals["tax_receipt_id"] = receipt.id + + donation.write(vals) + if donation.bank_statement_line_id: + donation._reconcile_donation_from_bank_statement() + donation.partner_id._update_donor_rank() + return + + def generate_each_tax_receipt(self): + self.ensure_one() + receipt = False + if ( + self.tax_receipt_option == "each" + and not self.tax_receipt_id + #and not self.company_currency_id.is_zero(self.tax_receipt_total) + ): + receipt_vals = self._prepare_each_tax_receipt() + receipt = self.env["donation.tax.receipt"].create(receipt_vals) + return receipt \ No newline at end of file diff --git a/gn_donations/views/donation_thanks_report.xml b/gn_donations/views/donation_thanks_report.xml new file mode 100644 index 0000000..7f5d18e --- /dev/null +++ b/gn_donations/views/donation_thanks_report.xml @@ -0,0 +1,240 @@ + + + + \ No newline at end of file diff --git a/gn_donations/views/internal_layout.xml b/gn_donations/views/internal_layout.xml new file mode 100644 index 0000000..081c4d7 --- /dev/null +++ b/gn_donations/views/internal_layout.xml @@ -0,0 +1,11 @@ + + + + \ No newline at end of file