def get_line1(cls, wizard, prod_name, qty, child_name):
        if child_name:
            if qty == 1:
                line = _('%d %s') % (qty, prod_name)
            else:
                line = _('%d %ss') % (qty, prod_name)
            res = export_utils.complete_line(35, line)

        else:
            res = export_utils.complete_line(35, prod_name)
        return res
    def _customize_records(self, records, properties):
        ''' We try to group lines if possible. '''
        grouped_lines = [records[0][1]]
        deb_account = records[1][1][72:81]
        ref = records[1][1][87:114]
        new_line = records[1][1]
        trans_id = 1
        nb_grouped = 1
        nb_transactions = 0

        for tuple in records[2:]:
            pay_line = tuple[0]
            line = tuple[1]
            if not pay_line:  # It's a header or total records
                # It's a total. We update trans_id and nb_transactions
                if line[35:37] == '97':
                    line = line[:37] + str(trans_id + 1).zfill(6) + \
                        line[43:53] + str(trans_id).zfill(6) + line[59:]
                    nb_transactions += trans_id
                    trans_id = 0
                grouped_lines.append(new_line)
                new_line = line
                deb_account = ''
                ref = ''
                continue
            if line[72:81] != deb_account or line[87:114] != ref:
                grouped_lines.append(new_line)
                trans_id += 1
                deb_account = line[72:81]
                ref = line[87:114]
                new_line = line
                new_line = new_line[:37] + \
                    str(trans_id).zfill(6) + new_line[43:]
                nb_grouped = 1
            else:
                nb_grouped += 1
                new_amount = float(
                    new_line[53:66]) / 100 + float(line[53:66]) / 100
                new_amount = self._format_number(new_amount, 13)
                new_com = export_utils.complete_line(
                    140, _('debit for %d period(s)') % nb_grouped)
                new_line = new_line[:53] + new_amount + \
                    new_line[66:402] + new_com + new_line[542:]

        grouped_lines.append(new_line)
        properties['nb_transactions'] = nb_transactions

        return grouped_lines
    def _customize_lines(self, lsv_lines, properties):
        ''' We try to group lines if possible. '''
        grouped_lines = []
        deb_iban = lsv_lines[0][1][237:271]
        treatment_date = lsv_lines[0][1][5:13]
        ref = lsv_lines[0][1][552:579]
        new_line = lsv_lines[0][1]
        seq_nb = 1
        nb_grouped = 1

        for tuple in lsv_lines[1:-1]:
            line = tuple[1]
            if line[237:271] != deb_iban or line[5:13] != treatment_date or \
                    line[552:579] != ref:
                grouped_lines.append(new_line)
                seq_nb += 1
                deb_iban = line[237:271]
                treatment_date = line[237:271]
                ref = line[552:579]
                new_line = line
                new_line = new_line[:36] + str(seq_nb).zfill(7) + \
                    new_line[43:]
                nb_grouped = 1
            else:

                nb_grouped += 1
                new_amount = float(
                    new_line[51:63].replace(',', '.')) + \
                    float(line[51:63].replace(',', '.'))
                new_amount = self._format_number(new_amount, 12)
                new_com = export_utils.complete_line(
                    140, _('debit for %d period(s)') % nb_grouped)
                new_line = new_line[:51] + new_amount + \
                    new_line[63:411] + new_com + new_line[551:]

        grouped_lines.append(new_line)
        seq_nb += 1
        grouped_lines.append(
            lsv_lines[-1][1][:17] + str(seq_nb).zfill(7) +
            lsv_lines[-1][1][24:])
        properties['seq_nb'] = seq_nb

        return grouped_lines
    def _customize_lines(self, lsv_lines, properties):
        ''' We try to group lines if possible. '''
        grouped_lines = []
        deb_iban = lsv_lines[0][1][237:271]
        treatment_date = lsv_lines[0][1][5:13]
        ref = lsv_lines[0][1][552:579]
        new_line = lsv_lines[0][1]
        seq_nb = 1
        nb_grouped = 1

        for tuple in lsv_lines[1:-1]:
            line = tuple[1]
            if line[237:271] != deb_iban or line[5:13] != treatment_date or \
                    line[552:579] != ref:
                grouped_lines.append(new_line)
                seq_nb += 1
                deb_iban = line[237:271]
                treatment_date = line[237:271]
                ref = line[552:579]
                new_line = line
                new_line = new_line[:36] + str(seq_nb).zfill(7) + \
                    new_line[43:]
                nb_grouped = 1
            else:

                nb_grouped += 1
                new_amount = float(
                    new_line[51:63].replace(',', '.')) + \
                    float(line[51:63].replace(',', '.'))
                new_amount = self._format_number(new_amount, 12)
                new_com = export_utils.complete_line(
                    140,
                    _('debit for %d period(s)') % nb_grouped)
                new_line = new_line[:51] + new_amount + \
                    new_line[63:411] + new_com + new_line[551:]

        grouped_lines.append(new_line)
        seq_nb += 1
        grouped_lines.append(lsv_lines[-1][1][:17] + str(seq_nb).zfill(7) +
                             lsv_lines[-1][1][24:])
        properties['seq_nb'] = seq_nb

        return grouped_lines
    def get_communications(cls, wizard, line):
        ''' We look for products in invoices to generate an appropriate
            communication. If we have enough space, add period informations.
        '''
        ######################################################################
        # As communications have to be in partner language and not in user   #
        # language, we update the context with partner lang. This way, the   #
        # right translation is used.                                         #
        # We also backup the context lang to restore it after with the user  #
        # language.                                                          #
        # Beside of this, we also set the locale to the partner language, in #
        # order to get the month name in the correct language.               #
        ######################################################################

        # use with_context pour l'objet qui utilise le context
        # is ca sera -> invoice_obj = wit...[].with_context({lang= lin..}
        locale.setlocale(locale.LC_ALL,
                         [wizard.env.context.get('lang'), 'utf8'])
        ######################################################################
        # We don't use move_line_id.invoice because it's really slow (the    #
        # invoice field is in fact a function field with some stuff not used #
        # in this context. Using a search and browse method made the process #
        # time go from 25ms to 10ms ! We could go down to 7 ms with a low    #
        # level SQL query, but the gain isn't important enough. We prefer    #
        # keep the code clean and lose 3 seconds on 1'000 payment lines.     #
        ######################################################################
        invoice_obj = wizard.env['account.invoice'].with_context(
            lang=line.partner_id.lang)
        invoice = invoice_obj.search(
            [('move_id', '=', line.move_line_id.move_id.id)], limit=1)
        if not invoice:
            return ''

        products = [(l.product_id.product_tmpl_id.name, l.quantity,
                     l.child_name) for l in invoice.invoice_line
                    if l.product_id.name_template and
                    (l.child_name and
                     'sponsorship' in l.product_id.name_template.lower() or
                     'gift' in l.product_id.name_template.lower() or not
                    l.child_name)]
        if not products:
            return ''

        # Reduction on keys -> Dict with total per product
        prod_dict = collections.defaultdict(int)
        qties = collections.defaultdict(list)
        names = {}
        for prod_name, qty, child_name in products:
            prod_dict[prod_name] += 1
            qties[prod_name].append(qty)
            names[prod_name] = child_name
        # List of ordered by quantity tuples (product, quantity)
        prod_dict_sort = sorted(
            prod_dict.iteritems(), key=operator.itemgetter(1), reverse=True)

        communication = ''
        ######################################################################
        # If nb products = 1 or 2, we write product name, quantity, child    #
        # name and period                                                    #
        # (as product are sponsorships or funds).                            #
        #                                                                    #
        # If nb products = 3 or 4, we write product name and quantity.       #
        #                                                                    #
        # If nb products > 4, we write the 3 products with most quantity     #
        # (name + quantity) and on the last line "x other engagements".      #
        ######################################################################
        nb_products = len(prod_dict_sort)
        if nb_products in [1, 2]:
            cur_date = datetime.strptime(
                invoice.date_due, DEFAULT_SERVER_DATE_FORMAT)
            for prod_name, qty in prod_dict_sort:
                communication += cls.get_line1(wizard, prod_name, qty,
                                               names[prod_name])
                mx = int(max(qties[prod_name]))
                if mx == 1:
                    line2 = ''
                    if _('gift') not in prod_name.lower():
                        line2 += _('period: %s ') % cur_date.strftime(
                            "%B").decode('utf-8')
                    if names[prod_name] and prod_dict[prod_name] == 1:
                        line2 += str(unidecode(names[prod_name]))

                    communication += export_utils.complete_line(35, line2)
                else:
                    beg_date = cur_date - relativedelta(months=mx - 1)
                    communication += export_utils.complete_line(
                        35, _('period: %s to %s') %
                        (beg_date.strftime("%B").decode('utf-8'),
                         cur_date.strftime("%B").decode('utf-8')))
        elif nb_products in [3, 4]:
            for prod_name, qty in prod_dict_sort:
                communication += cls.get_line1(wizard, prod_name, qty,
                                               names[prod_name])
        elif nb_products > 4:
            for prod_name, qty in prod_dict_sort[:3]:
                communication += cls.get_line1(wizard, prod_name, qty,
                                               names[prod_name])
            communication += export_utils.complete_line(
                35, _('%d other engagements') %
                sum([tup[1] for tup in prod_dict_sort[3:]]))

        return communication