(self)
Creates restitution records in 349
Creates restitution records in 349
Creates restitution records in 349
def _create_349_refund_records(self):
        """Creates restitution records in 349"""
        self.ensure_one()
        detail_obj = self.env["l10n.es.aeat.mod349.partner_record_detail"]
        obj = self.env["l10n.es.aeat.mod349.partner_refund"]
        refund_detail_obj = self.env["l10n.es.aeat.mod349.partner_refund_detail"]
        move_line_obj = self.env["account.move.line"]
        taxes = self._get_taxes()
        data = {}
        # This is for avoiding to find same lines several times
        visited_details = self.env["l10n.es.aeat.mod349.partner_record_detail"]
        visited_move_lines = self.env["account.move.line"]
        groups = {}
        for refund_detail in self.partner_refund_detail_ids:
            move_line = refund_detail.refund_line_id
            origin_invoice = move_line.move_id.reversed_entry_id
            groups.setdefault(origin_invoice, refund_detail_obj)
            groups[origin_invoice] += refund_detail
        for origin_invoice in groups:
            refund_details = groups[origin_invoice]
            refund_detail = first(refund_details)
            move_line = refund_detail.refund_line_id
            partner = move_line.partner_id
            op_key = move_line.l10n_es_aeat_349_operation_key
            if not origin_invoice:
                # TODO: Instead continuing, generate an empty record and a msg
                continue
            # Fetch the latest presentation made for this move
            original_details = detail_obj.search(
                [
                    ("move_line_id.move_id", "=", origin_invoice.id),
                    ("partner_record_id.operation_key", "=", op_key),
                    ("id", "not in", visited_details.ids),
                ],
                order="report_id desc",
            )
            # we add all of them to visited, as we don't want to repeat
            visited_details |= original_details
            if original_details:
                # There's at least one previous 349 declaration report
                report = original_details.mapped("report_id")[:1]
                partner_id = original_details.mapped("partner_id")[:1]
                original_details = original_details.filtered(
                    lambda d: d.report_id == report
                )
                origin_amount = sum(original_details.mapped("amount_untaxed"))
                period_type = report.period_type
                year = str(report.year)

                # Sum all details period origin
                all_details_period = detail_obj.search(
                    [
                        ("partner_id", "=", partner_id.id),
                        ("partner_record_id.operation_key", "=", op_key),
                        ("report_id", "=", report.id),
                    ],
                    order="report_id desc",
                )
                origin_amount = sum(all_details_period.mapped("amount_untaxed"))

                # If there are intermediate periods between the original
                # period and the period where the rectification is taking
                # place, it's necessary to check if there is any rectification
                # of the original period in between these periods. This
                # happens in this way because the right original_amount
                # will be the value of the total_operation_amount
                # corresponding to the last period found in between the periods
                other_invoice_period = (
                    all_details_period.mapped("move_id") - origin_invoice
                )
                refund_invoice_ids = self.env["account.move"].search(
                    [("reversed_entry_id", "in", other_invoice_period.ids)]
                )
                if refund_invoice_ids:
                    last_refund_detail = refund_detail_obj.search(
                        [
                            ("report_id.date_start", ">", report.date_end),
                            ("report_id.date_end", "<", self.date_start),
                            ("move_id", "in", refund_invoice_ids.ids),
                        ],
                        order="date desc",
                        limit=1,
                    )
                    if last_refund_detail:
                        origin_amount = (
                            last_refund_detail.refund_id.total_operation_amount
                        )

            else:
                # There's no previous 349 declaration report in Odoo
                original_amls = move_line_obj.search(
                    [
                        ("tax_ids", "in", taxes.ids),
                        ("l10n_es_aeat_349_operation_key", "=", op_key),
                        ("move_id", "=", origin_invoice.id),
                    ]
                )
                origin_amount = abs(
                    sum((original_amls - visited_move_lines).mapped("balance"))
                )
                visited_move_lines |= original_amls
                # We have to guess the period type, as we don't have that info
                # through move lines. Inferred from:
                # * current record period scheme (monthly/quarterly/yearly)
                # * date of the move line
                if original_amls:
                    original_move = original_amls[:1]
                    year = str(original_move.date.year)
                    month = "%02d" % (original_move.date.month)
                else:
                    continue  # We can't find information to attach to
                if self.period_type == "0A":
                    period_type = "0A"
                elif self.period_type in ("1T", "2T", "3T", "4T"):
                    period_type = "%sT" % int(math.ceil(int(month) / 3.0))
                else:
                    period_type = month
            key = (partner, op_key, period_type, year)
            key_vals = data.setdefault(
                key, {"original_amount": 0, "refund_details": refund_detail_obj}
            )
            key_vals["original_amount"] += origin_amount
            key_vals["refund_details"] += refund_details
        for key, key_vals in data.items():
            partner, op_key, period_type, year = key
            partner_refund = obj.create(
                {
                    "report_id": self.id,
                    "partner_id": partner.id,
                    "partner_vat": partner.vat,
                    "operation_key": op_key,
                    "country_id": partner.country_id.id,
                    "total_origin_amount": key_vals["original_amount"],
                    "period_type": period_type,
                    "year": year,
                }
            )
            key_vals["refund_details"].write({"refund_id": partner_refund.id})
def _create_349_refund_records ( self ) : self . ensure_one ( ) detail_obj = self . env [ "l10n.es.aeat.mod349.partner_record_detail" ] obj = self . env [ "l10n.es.aeat.mod349.partner_refund" ] refund_detail_obj = self . env [ "l10n.es.aeat.mod349.partner_refund_detail" ] move_line_obj = self . env [ "account.move.line" ] taxes = self . _get_taxes ( ) data = { } # This is for avoiding to find same lines several times visited_details = self . env [ "l10n.es.aeat.mod349.partner_record_detail" ] visited_move_lines = self . env [ "account.move.line" ] groups = { } for refund_detail in self . partner_refund_detail_ids : move_line = refund_detail . refund_line_id origin_invoice = move_line . move_id . reversed_entry_id groups . setdefault ( origin_invoice , refund_detail_obj ) groups [ origin_invoice ] += refund_detail for origin_invoice in groups : refund_details = groups [ origin_invoice ] refund_detail = first ( refund_details ) move_line = refund_detail . refund_line_id partner = move_line . partner_id op_key = move_line . l10n_es_aeat_349_operation_key if not origin_invoice : # TODO: Instead continuing, generate an empty record and a msg continue # Fetch the latest presentation made for this move original_details = detail_obj . search ( [ ( "move_line_id.move_id" , "=" , origin_invoice . id ) , ( "partner_record_id.operation_key" , "=" , op_key ) , ( "id" , "not in" , visited_details . ids ) , ] , order = "report_id desc" , ) # we add all of them to visited, as we don't want to repeat visited_details |= original_details if original_details : # There's at least one previous 349 declaration report report = original_details . mapped ( "report_id" ) [ : 1 ] partner_id = original_details . mapped ( "partner_id" ) [ : 1 ] original_details = original_details . filtered ( lambda d : d . report_id == report ) origin_amount = sum ( original_details . mapped ( "amount_untaxed" ) ) period_type = report . period_type year = str ( report . year ) # Sum all details period origin all_details_period = detail_obj . search ( [ ( "partner_id" , "=" , partner_id . id ) , ( "partner_record_id.operation_key" , "=" , op_key ) , ( "report_id" , "=" , report . id ) , ] , order = "report_id desc" , ) origin_amount = sum ( all_details_period . mapped ( "amount_untaxed" ) ) # If there are intermediate periods between the original # period and the period where the rectification is taking # place, it's necessary to check if there is any rectification # of the original period in between these periods. This # happens in this way because the right original_amount # will be the value of the total_operation_amount # corresponding to the last period found in between the periods other_invoice_period = ( all_details_period . mapped ( "move_id" ) - origin_invoice ) refund_invoice_ids = self . env [ "account.move" ] . search ( [ ( "reversed_entry_id" , "in" , other_invoice_period . ids ) ] ) if refund_invoice_ids : last_refund_detail = refund_detail_obj . search ( [ ( "report_id.date_start" , ">" , report . date_end ) , ( "report_id.date_end" , "<" , self . date_start ) , ( "move_id" , "in" , refund_invoice_ids . ids ) , ] , order = "date desc" , limit = 1 , ) if last_refund_detail : origin_amount = ( last_refund_detail . refund_id . total_operation_amount ) else : # There's no previous 349 declaration report in Odoo original_amls = move_line_obj . search ( [ ( "tax_ids" , "in" , taxes . ids ) , ( "l10n_es_aeat_349_operation_key" , "=" , op_key ) , ( "move_id" , "=" , origin_invoice . id ) , ] ) origin_amount = abs ( sum ( ( original_amls - visited_move_lines ) . mapped ( "balance" ) ) ) visited_move_lines |= original_amls # We have to guess the period type, as we don't have that info # through move lines. Inferred from: # * current record period scheme (monthly/quarterly/yearly) # * date of the move line if original_amls : original_move = original_amls [ : 1 ] year = str ( original_move . date . year ) month = "%02d" % ( original_move . date . month ) else : continue # We can't find information to attach to if self . period_type == "0A" : period_type = "0A" elif self . period_type in ( "1T" , "2T" , "3T" , "4T" ) : period_type = "%sT" % int ( math . ceil ( int ( month ) / 3.0 ) ) else : period_type = month key = ( partner , op_key , period_type , year ) key_vals = data . setdefault ( key , { "original_amount" : 0 , "refund_details" : refund_detail_obj } ) key_vals [ "original_amount" ] += origin_amount key_vals [ "refund_details" ] += refund_details for key , key_vals in data . items ( ) : partner , op_key , period_type , year = key partner_refund = obj . create ( { "report_id" : self . id , "partner_id" : partner . id , "partner_vat" : partner . vat , "operation_key" : op_key , "country_id" : partner . country_id . id , "total_origin_amount" : key_vals [ "original_amount" ] , "period_type" : period_type , "year" : year , } ) key_vals [ "refund_details" ] . write ( { "refund_id" : partner_refund . id } )