Exemple #1
0
    def _compute_price_tax(self):
        currency = self.invoice_id and self.invoice_id.currency_id or None
        prec = currency.decimal_places
        price = self.price_unit * (1 - (self.discount or 0.0) / 100.0)
        q = 1
        unit_taxes = False
        taxes = False
        if self.invoice_line_tax_ids:
            if self.invoice_id.inclusive:
                unit_taxes = self.invoice_line_tax_ids.with_context(
                    price_include=True,
                    include_base_amount=True).compute_all_inc(
                        price,
                        currency,
                        q,
                        product=self.product_id,
                        partner=self.invoice_id.partner_id)
                taxes = self.invoice_line_tax_ids.with_context(
                    price_include=True,
                    include_base_amount=True).compute_all_inc(
                        price,
                        currency,
                        self.quantity,
                        product=self.product_id,
                        partner=self.invoice_id.partner_id)
            else:
                unit_taxes = self.invoice_line_tax_ids.compute_all(
                    price,
                    currency,
                    q,
                    product=self.product_id,
                    partner=self.invoice_id.partner_id)
                taxes = self.invoice_line_tax_ids.compute_all(
                    price,
                    currency,
                    self.quantity,
                    product=self.product_id,
                    partner=self.invoice_id.partner_id)

        self.price_unit_tax = unit_taxes[
            'total_excluded'] if unit_taxes else price
        self.price_subtotal_tax = taxes[
            'total_excluded'] if taxes else self.quantity * price
        self.price_subtotal_taxinc = taxes[
            'total_included'] if taxes else self.quantity * price
        if self.invoice_id:
            self.price_subtotal_tax = round(self.price_subtotal_tax, prec)
            self.price_subtotal_taxinc = round(self.price_subtotal_taxinc,
                                               prec)
            self.price_unit_tax = self.invoice_id.currency_id.round(
                self.price_unit_tax)
Exemple #2
0
 def __new_get_work_days_data(self, from_datetime, to_datetime,
                              calendar=None):
     if not hasattr(self, '_get_work_hours'):
         return self.get_day_work_hours_count_original(
             from_datetime, to_datetime, calendar=calendar)
     days_count = 0.0
     total_work_time = timedelta()
     calendar = calendar or self.resource_calendar_id
     calendar = calendar.with_context(
         no_tz_convert=self.env.context.get('no_tz_convert', False))
     for day_intervals in calendar._iter_work_intervals(
             from_datetime, to_datetime, self.resource_id.id,
             compute_leaves=True):
         theoric_hours = self.get_day_work_hours_count(
             day_intervals[0][0].date(), calendar=calendar)
         # Here we introduce the hook method '_get_work_hours'.
         work_time = sum((self._get_work_hours(interval)
                          for interval in day_intervals), timedelta())
         total_work_time += work_time
         if theoric_hours:
             days_count += float_utils.round(
                 (work_time.total_seconds() / 3600 / theoric_hours) * 4) / 4
     return {
         'days': days_count,
         'hours': total_work_time.total_seconds() / 3600,
     }
Exemple #3
0
 def _compute_interest(self):
     for record in self:
         precision = record.env['decimal.precision'].precision_get(
             'Account')
         record.amount_interest = round(
             record.amount_currency * (record.percent_interest / 100),
             precision)
Exemple #4
0
    def _prepare_line(self, line, amounts, partner_id):
        company_id = self.env.user.company_id
        currency = company_id.currency_id
        prec = currency.decimal_places
        amount = round(abs(amounts[line.sequence]), prec)
        debit = line.move_line_type == 'dr'

        # if not debit and amounts[line.sequence] < 0.0:
        #     debit = True
        if line.move_line_type == 'dc' and amounts[line.sequence] > 0.0:
            debit = False
        elif line.move_line_type == 'dc' and amounts[line.sequence] < 0.0:
            debit = True
        if line.python_code and line.python_code.find('L(') != -1 and amounts[line.sequence] < 0.0:
            debit = False
        # if amount > 0 and debit:
        #     debit = False
        # if amount < 0 and not debit:
        #     debit = True
        # amount = abs(amounts[line.sequence])
        values = {
            'name': line.name,
            'journal_id': line.journal_id.id,
            'analytic_account_id': line.analytic_account_id.id,
            'analytic_tag_ids': line.analytic_tag_ids,
            'account_id': line.account_id.id,
            'date': self.accounting_date or time.strftime('%Y-%m-%d'),
            'date_maturity': self.date_due,
            'credit': not debit and amount or 0.0,
            'debit': debit and amount or 0.0,
            'partner_id': partner_id,
        }
        return values
Exemple #5
0
 def __new_get_work_days_data(self,
                              from_datetime,
                              to_datetime,
                              calendar=None):
     if not hasattr(self, "_get_work_hours"):
         return self.get_day_work_hours_count_original(from_datetime,
                                                       to_datetime,
                                                       calendar=calendar)
     days_count = 0.0
     total_work_time = timedelta()
     calendar = calendar or self.resource_calendar_id
     calendar = calendar.with_context(
         no_tz_convert=self.env.context.get("no_tz_convert", False))
     for day_intervals in calendar._iter_work_intervals(
             from_datetime,
             to_datetime,
             self.resource_id.id,
             compute_leaves=True,
     ):
         theoric_hours = self.get_day_work_hours_count(
             day_intervals[0][0].date(), calendar=calendar)
         work_time = sum(
             (self._get_work_hours(interval) for interval in day_intervals),
             timedelta(),
         )
         total_work_time += work_time
         if theoric_hours:
             days_count += (float_utils.round(
                 (work_time.total_seconds() / 3600 / theoric_hours) * 4) /
                            4)
     return {
         "days": days_count,
         "hours": total_work_time.total_seconds() / 3600,
     }
    def get_work_days_dashboard(self,
                                from_datetime,
                                to_datetime,
                                compute_leaves=False,
                                calendar=None,
                                domain=None):
        resource = self.resource_id
        calendar = calendar or self.resource_calendar_id

        if not from_datetime.tzinfo:
            from_datetime = from_datetime.replace(tzinfo=utc)
        if not to_datetime.tzinfo:
            to_datetime = to_datetime.replace(tzinfo=utc)
        from_full = from_datetime - timedelta(days=1)
        to_full = to_datetime + timedelta(days=1)
        intervals = calendar._attendance_intervals(from_full, to_full,
                                                   resource)
        day_total = defaultdict(float)
        for start, stop, meta in intervals:
            day_total[start.date()] += (stop - start).total_seconds() / 3600
        if compute_leaves:
            intervals = calendar._work_intervals(from_datetime, to_datetime,
                                                 resource, domain)
        else:
            intervals = calendar._attendance_intervals(from_datetime,
                                                       to_datetime, resource)
        day_hours = defaultdict(float)
        for start, stop, meta in intervals:
            day_hours[start.date()] += (stop - start).total_seconds() / 3600
        days = sum(
            float_utils.round(ROUNDING_FACTOR * day_hours[day] /
                              day_total[day]) / ROUNDING_FACTOR
            for day in day_hours)
        return days
Exemple #7
0
 def get_work_days_data(self,
                        from_datetime,
                        to_datetime,
                        calendar=None,
                        domain=None):
     days_count = 0.0
     total_work_time = timedelta()
     calendar = calendar or self.resource_calendar_id
     for day_intervals in calendar._iter_work_intervals(from_datetime,
                                                        to_datetime,
                                                        self.resource_id.id,
                                                        compute_leaves=True,
                                                        domain=domain):
         theoric_hours = self.get_day_work_hours_count(
             day_intervals[0][0].date(), calendar=calendar)
         work_time = sum(
             (interval[1] - interval[0] for interval in day_intervals),
             timedelta())
         total_work_time += work_time
         if theoric_hours:
             days_count += float_utils.round(
                 (work_time.total_seconds() / 3600 / theoric_hours) * 4) / 4
     return {
         'days': days_count,
         'hours': total_work_time.total_seconds() / 3600,
     }
Exemple #8
0
    def _compute_amount(self):
        for line in self:
            desc1 = 1 - (line.desc1 or 0.0) / 100.0
            desc2 = 1 - (line.desc2 or 0.0) / 100.0
            price = line.price_unit * desc1 * desc2

            if line.qty_received > 0 and line.order_id.state in ('done',
                                                                 'purchase'):
                quantity = line.qty_received
            else:
                quantity = line.product_qty
            price_reduce = line.price_unit * (1.0 - line.desc1 / 100.0) * (
                1.0 - line.desc2 / 100.0)
            line_sub_total = quantity * line.price_unit
            taxes = line.taxes_id.compute_all(price,
                                              line.order_id.currency_id,
                                              quantity,
                                              product=line.product_id,
                                              partner=line.order_id.partner_id)

            line.price_reduce = price_reduce
            line.line_sub_total = line_sub_total
            line.price_tax = taxes['total_included'] - taxes['total_excluded']
            line.price_total = taxes['total_included']
            line.price_subtotal = taxes['total_excluded']
            round_tax = False if line.company_id.tax_calculation_rounding_method == 'round_globally' else True
            if round_tax:
                line.subtotal_desc = line.order_id.currency_id.round(
                    round(line.price_unit *
                          quantity, line.order_id.currency_id.decimal_places) -
                    taxes['total_excluded'])
            else:
                line.subtotal_desc = (line.price_unit *
                                      quantity) - taxes['total_excluded']
Exemple #9
0
 def _compute_available_days(self):
     for interval in self:
         available_hours = interval.day_id.available_hours
         hours = interval.available_hours
         interval.available_days = (
             float_utils.round(ROUNDING_FACTOR * hours / available_hours) /
             ROUNDING_FACTOR) if available_hours else 0.0
Exemple #10
0
 def _inverse_requested_hours(self):
     for interval in self:
         amount = (float_utils.round(
             ROUNDING_FACTOR *
             (interval.requested_hours / interval.available_hours)) /
                   ROUNDING_FACTOR) if interval.available_hours else 0.0
         interval.request_amount = max(min(amount, 1.0), 0.0)
Exemple #11
0
    def __new_get_work_days_data(
            self, from_datetime, to_datetime, compute_leaves=True,
            calendar=None, domain=None
    ):
        """
            By default the resource calendar is used, but it can be
            changed using the `calendar` argument.

            `domain` is used in order to recognise the leaves to take,
            None means default value ('time_type', '=', 'leave')

            Returns a dict {'days': n, 'hours': h} containing the
            quantity of working time expressed as days and as hours.
        """
        resource = self.resource_id
        calendar = calendar or self.resource_calendar_id

        # naive datetimes are made explicit in UTC
        if not from_datetime.tzinfo:
            from_datetime = from_datetime.replace(tzinfo=utc)
        if not to_datetime.tzinfo:
            to_datetime = to_datetime.replace(tzinfo=utc)

        # total hours per day: retrieve attendances with one extra day margin,
        # in order to compute the total hours on the first and last days
        from_full = from_datetime - timedelta(days=1)
        to_full = to_datetime + timedelta(days=1)
        intervals = calendar._attendance_intervals(
            from_full, to_full, resource
        )
        day_total = defaultdict(float)
        for start, stop, meta in intervals:
            day_total[start.date()] += (stop - start).total_seconds() / 3600

        # actual hours per day
        if compute_leaves:
            intervals = calendar._work_intervals(
                from_datetime, to_datetime, resource, domain
            )
        else:
            intervals = calendar._attendance_intervals(
                from_datetime, to_datetime, resource
            )
        day_hours = defaultdict(float)
        for start, stop, meta in intervals:
            day_hours[start.date()] += self._get_work_hours(start, stop, meta)

        # compute number of days as quarters
        days = sum(
            float_utils.round(
                ROUNDING_FACTOR * day_hours[day] / day_total[day]
            ) / ROUNDING_FACTOR
            for day in day_hours
        )
        return {
            'days': days,
            'hours': sum(day_hours.values()),
        }
Exemple #12
0
    def _get_leave_days(self, from_datetime, to_datetime):
        """
        Compute number of days on used from the allocation, without global
        leaves taken into account, other leaves are irrelevant since it's
        ensured that no two leaves overlap.
        """
        self.ensure_one()

        # NOTE: This mimics ResourceMixin.get_leave_days_data() w/ changes

        calendar = self.employee_id.resource_calendar_id

        if not from_datetime.tzinfo:
            from_datetime = from_datetime.replace(tzinfo=utc)
        if not to_datetime.tzinfo:
            to_datetime = to_datetime.replace(tzinfo=utc)

        # total hours per day: retrieve attendances with one extra day margin,
        # in order to compute the total hours on the first and last days
        intervals = calendar._attendance_intervals(
            from_datetime - timedelta(days=1),
            to_datetime + timedelta(days=1),
            self.employee_id.resource_id,
        )
        day_total = defaultdict(float)
        for start, stop, meta in intervals:
            day_total[start.date()] += (stop - start).total_seconds() / 3600

        # actual hours per day
        attendance_intervals = calendar._attendance_intervals(
            from_datetime,
            to_datetime,
            self.employee_id.resource_id,
        )
        leave_intervals = calendar._leave_intervals(
            from_datetime,
            to_datetime,
            self.employee_id.resource_id,
            domain=[('holiday_status_id', '=', self.holiday_status_id.id),
                    ('time_type', '=', 'leave')],
        )
        global_intervals = calendar._leave_intervals(
            from_datetime,
            to_datetime,
            None,
        )
        intervals = (attendance_intervals &
                     (leave_intervals - global_intervals))
        day_hours = defaultdict(float)
        for start, stop, meta in intervals:
            day_hours[start.date()] += (stop - start).total_seconds() / 3600

        # compute number of days as quarters
        return sum(
            float_utils.round(ROUNDING_FACTOR * day_hours[day] /
                              day_total[day]) / ROUNDING_FACTOR
            for day in day_hours)
Exemple #13
0
    def _get_worked_days(self, from_datetime, to_datetime):
        """
        Compute number of worked days, that is computed as number workable days
        without unpaid leaves (that are not on global leaves) counted in.
        """
        self.ensure_one()

        # NOTE: This mimics ResourceMixin.get_work_days_data() w/ changes

        calendar = self.employee_id.resource_calendar_id

        if not from_datetime.tzinfo:
            from_datetime = from_datetime.replace(tzinfo=utc)
        if not to_datetime.tzinfo:
            to_datetime = to_datetime.replace(tzinfo=utc)

        # total hours per day: retrieve attendances with one extra day margin,
        # in order to compute the total hours on the first and last days
        intervals = calendar._attendance_intervals(
            from_datetime - timedelta(days=1),
            to_datetime + timedelta(days=1),
            self.employee_id.resource_id,
        )
        day_total = defaultdict(float)
        for start, stop, meta in intervals:
            day_total[start.date()] += (stop - start).total_seconds() / 3600

        # actual hours per day
        attendance_intervals = calendar._attendance_intervals(
            from_datetime,
            to_datetime,
            self.employee_id.resource_id,
        )
        unpaid_intervals = calendar._leave_intervals(
            from_datetime,
            to_datetime,
            self.employee_id.resource_id,
            domain=[('unpaid', '=', True), ('time_type', '=', 'leave')],
        )
        global_intervals = calendar._leave_intervals(
            from_datetime,
            to_datetime,
            None,
        )
        intervals = (attendance_intervals -
                     (unpaid_intervals - global_intervals))
        day_hours = defaultdict(float)
        for start, stop, meta in intervals:
            day_hours[start.date()] += (stop - start).total_seconds() / 3600

        # compute number of days as quarters
        return sum(
            float_utils.round(ROUNDING_FACTOR * day_hours[day] /
                              day_total[day]) / ROUNDING_FACTOR
            for day in day_hours)
 def get_leaves_day_count(self, from_datetime, to_datetime, calendar=None):
     """ Return the number of leave days for the resource, taking into account
     attendances. An optional calendar can be given in case multiple calendars
     can be used on the resource. """
     days_count = 0.0
     calendar = calendar or self.resource_calendar_id
     for day_intervals in calendar._iter_leave_intervals(from_datetime, to_datetime, self.resource_id.id):
         theoric_hours = self.get_day_work_hours_count(day_intervals[0][0].date(), calendar=calendar)
         leave_time = sum((interval[1] - interval[0] for interval in day_intervals), timedelta())
         days_count += float_utils.round((leave_time.total_seconds() / 3600 / theoric_hours) * 4) / 4
     return days_count
 def _get_partner_rate(self):
     for obj in self:
         partner_rate = 0.0
         total_messages = len(
             [x.id for x in obj.website_message_ids if x.message_rate > 0])
         if total_messages > 0:
             total_rate = sum(
                 [x.message_rate for x in obj.website_message_ids])
             # getcontext().prec = 3
             partner_rate = float(float(total_rate) / float(total_messages))
             # partner_rate = Decimal( total_rate ) / Decimal( total_messages )
         obj.partner_rate = round(partner_rate, 2)
Exemple #16
0
 def get_leaves_days_data(self, from_datetime, to_datetime, calendar=None, domain=None):
     days_count = 0.0
     total_leave_time = timedelta()
     calendar = calendar or self.resource_calendar_id
     for day_intervals in calendar._iter_leave_intervals(from_datetime, to_datetime, self.resource_id.id, domain=domain):
         theoric_hours = self.get_day_work_hours_count(day_intervals[0][0].date(), calendar=calendar)
         leave_time = sum((interval[1] - interval[0] for interval in day_intervals), timedelta())
         total_leave_time += leave_time
         days_count += float_utils.round((leave_time.total_seconds() / 3600 / theoric_hours) * 4) / 4
     return {
         'days': days_count,
         'hours': total_leave_time.total_seconds() / 3600,
     }
Exemple #17
0
 def get_work_days_data(
     self,
     from_datetime,
     to_datetime,
     compute_leaves=True,
     calendar=None,
     domain=None,
 ):
     if calendar or not hasattr(self, "contract_ids"):
         return super().get_work_days_data(from_datetime, to_datetime,
                                           compute_leaves, calendar, domain)
     # we need the normal work time per day for each day to be able to
     # compute the fraction of day that the number of hours represents.
     # this is defined in the calendar of the employee, which must be the
     # same as the one of the company, and which must contain full-day
     # hours for each day.
     #
     # we need full days, so we replace the hours to start and stop at
     # midnight in the timezone of the resource.
     #
     # the provided domain is to exclude leaves from the computation, as
     # explained in list_work_time_per_day().
     from_datetime, to_datetime = self._localize_datetimes(
         from_datetime, to_datetime)
     normal_work_time_per_day = dict(super().list_work_time_per_day(
         from_datetime.replace(hour=0, minute=0, second=0, microsecond=0),
         to_datetime.replace(hour=0, minute=0, second=0, microsecond=0) +
         datetime.timedelta(days=1),
         self.resource_calendar_id,
         [("calendar_id", "=", False)],
     ))
     if compute_leaves:
         work_time_per_day = self.list_work_time_per_day(from_datetime,
                                                         to_datetime,
                                                         calendar=None,
                                                         domain=domain)
     else:
         work_time_per_day = self.list_normal_work_time_per_day(
             from_datetime, to_datetime, domain=domain)
     num_days = 0.0
     num_hours = 0.0
     for day, work_time in work_time_per_day:
         if work_time == 0.0:
             continue
         normal_work_time = normal_work_time_per_day[day]
         # we use the same rounding computation as in
         # resource.resource_mixin.get_work_days_data().
         num_days += (float_utils.round(ROUNDING_FACTOR * work_time /
                                        normal_work_time) / ROUNDING_FACTOR)
         num_hours += work_time
     return {"days": num_days, "hours": num_hours}
Exemple #18
0
 def _get_price(self, cr, uid, inv, company_currency, i_line, price_unit):
     cur_obj = self.pool.get('res.currency')
     decimal_precision = self.pool.get('decimal.precision')
     if inv.currency_id.id != company_currency:
         price = cur_obj.compute(cr,
                                 uid,
                                 company_currency,
                                 inv.currency_id.id,
                                 price_unit * i_line.quantity,
                                 context={'date': inv.date_invoice})
     else:
         price = price_unit * i_line.quantity
     return round(price,
                  decimal_precision.precision_get(cr, uid, 'Account'))
Exemple #19
0
    def __new__get_days_data(self, intervals, day_total):
        day_hours = defaultdict(float)
        for start, stop, meta in intervals:
            day_hours[start.date()] += self._get_work_hours_interval(
                start, stop, meta)

        # compute number of days as quarters
        days = sum(
            float_utils.round(ROUNDING_FACTOR * day_hours[day] /
                              day_total[day]) / ROUNDING_FACTOR
            for day in day_hours)
        return {
            "days": days,
            "hours": sum(day_hours.values()),
        }
Exemple #20
0
    def get_work_days_data(self, from_datetime, to_datetime, compute_leaves=True, calendar=None, domain=None):
        """
            By default the resource calendar is used, but it can be
            changed using the `calendar` argument.

            `domain` is used in order to recognise the leaves to take,
            None means default value ('time_type', '=', 'leave')

            Returns a dict {'days': n, 'hours': h} containing the
            quantity of working time expressed as days and as hours.
        """
        resource = self.resource_id
        calendar = calendar or self.resource_calendar_id

        # naive datetimes are made explicit in UTC
        if not from_datetime.tzinfo:
            from_datetime = from_datetime.replace(tzinfo=utc)
        if not to_datetime.tzinfo:
            to_datetime = to_datetime.replace(tzinfo=utc)

        # total hours per day: retrieve attendances with one extra day margin,
        # in order to compute the total hours on the first and last days
        from_full = from_datetime - timedelta(days=1)
        to_full = to_datetime + timedelta(days=1)
        intervals = calendar._attendance_intervals(from_full, to_full, resource)
        day_total = defaultdict(float)
        for start, stop, meta in intervals:
            day_total[start.date()] += (stop - start).total_seconds() / 3600

        # actual hours per day
        if compute_leaves:
            intervals = calendar._work_intervals(from_datetime, to_datetime, resource, domain)
        else:
            intervals = calendar._attendance_intervals(from_datetime, to_datetime, resource)
        day_hours = defaultdict(float)
        for start, stop, meta in intervals:
            day_hours[start.date()] += (stop - start).total_seconds() / 3600

        # compute number of days as quarters
        days = sum(
            float_utils.round(ROUNDING_FACTOR * day_hours[day] / day_total[day]) / ROUNDING_FACTOR
            for day in day_hours
        )
        return {
            'days': days,
            'hours': sum(day_hours.values()),
        }
Exemple #21
0
    def _get_days_data(self, intervals, day_total):
        """
        helper function to compute duration of `intervals`
        expressed in days and hours.
        `day_total` is a dict {date: n_hours} with the number of hours for each day.
        """
        day_hours = defaultdict(float)
        for start, stop, meta in intervals:
            day_hours[start.date()] += (stop - start).total_seconds() / 3600

        # compute number of days as quarters
        days = sum(
            float_utils.round(ROUNDING_FACTOR * day_hours[day] / day_total[day]) / ROUNDING_FACTOR
            for day in day_hours
        )
        return {
            'days': days,
            'hours': sum(day_hours.values()),
        }
Exemple #22
0
    def _get_days_data(self, intervals, day_total):
        """
        helper function to compute duration of `intervals`
        expressed in days and hours.
        `day_total` is a dict {date: n_hours} with the number of hours for each day.
        """
        day_hours = defaultdict(float)
        for start, stop, meta in intervals:
            day_hours[start.date()] += (stop - start).total_seconds() / 3600

        # compute number of days as quarters
        days = sum(
            float_utils.round(ROUNDING_FACTOR * day_hours[day] /
                              day_total[day]) / ROUNDING_FACTOR
            for day in day_hours)
        return {
            'days': days,
            'hours': sum(day_hours.values()),
        }
Exemple #23
0
 def create_invoice_plan(self, num_installment, installment_date, interval,
                         interval_type, advance):
     self.ensure_one()
     self.invoice_plan_ids.unlink()
     invoice_plans = []
     if num_installment <= 1:
         raise UserError(_('Number Installment must greater than 1'))
     Decimal = self.env['decimal.precision']
     prec = Decimal.precision_get('Product Unit of Measure')
     percent = round(1.0 / num_installment * 100, prec)
     percent_last = 100 - (percent * (num_installment - 1))
     # Advance
     if advance:
         vals = {
             'installment': 0,
             'plan_date': installment_date,
             'type': 'advance',
             'percent': 0.0
         }
         invoice_plans.append((0, 0, vals))
         installment_date = self._next_date(installment_date, interval,
                                            interval_type)
     # Normal
     for i in range(num_installment):
         this_installment = i + 1
         if num_installment == this_installment:
             percent = percent_last
         vals = {
             'installment': this_installment,
             'plan_date': installment_date,
             'type': 'installment',
             'percent': percent
         }
         invoice_plans.append((0, 0, vals))
         installment_date = self._next_date(installment_date, interval,
                                            interval_type)
     self.write({'invoice_plan_ids': invoice_plans})
     return True
Exemple #24
0
    def compute_all(self, price_unit, currency=None, quantity=1.0, product=None, partner=None):
        """ Returns all information required to apply taxes (in self + their children in case of a tax goup).
            We consider the sequence of the parent for group of taxes.
                Eg. considering letters as taxes and alphabetic order as sequence :
                [G, B([A, D, F]), E, C] will be computed as [A, D, F, C, E, G]

        RETURN: {
            'total_excluded': 0.0,    # Total without taxes
            'total_included': 0.0,    # Total with taxes
            'taxes': [{               # One dict for each tax in self and their children
                'id': int,
                'name': str,
                'amount': float,
                'sequence': int,
                'account_id': int,
                'refund_account_id': int,
                'analytic': boolean,
            }]
        } """
        if len(self) == 0:
            company_id = self.env.user.company_id
        else:
            company_id = self[0].company_id
        if not currency:
            currency = company_id.currency_id
        taxes = []
        # By default, for each tax, tax amount will first be computed
        # and rounded at the 'Account' decimal precision for each
        # PO/SO/invoice line and then these rounded amounts will be
        # summed, leading to the total amount for that tax. But, if the
        # company has tax_calculation_rounding_method = round_globally,
        # we still follow the same method, but we use a much larger
        # precision when we round the tax amount for each line (we use
        # the 'Account' decimal precision + 5), and that way it's like
        # rounding after the sum of the tax amounts of each line
        prec = currency.decimal_places

        # In some cases, it is necessary to force/prevent the rounding of the tax and the total
        # amounts. For example, in SO/PO line, we don't want to round the price unit at the
        # precision of the currency.
        # The context key 'round' allows to force the standard behavior.
        round_tax = False if company_id.tax_calculation_rounding_method == 'round_globally' else True
        round_total = True
        if 'round' in self.env.context:
            round_tax = bool(self.env.context['round'])
            round_total = bool(self.env.context['round'])

        if not round_tax:
            prec += 5

        base_values = self.env.context.get('base_values')
        if not base_values:
            total_excluded = total_included = base = round(price_unit * quantity, prec)
        else:
            total_excluded, total_included, base = base_values

        # Sorting key is mandatory in this case. When no key is provided, sorted() will perform a
        # search. However, the search method is overridden in account.tax in order to add a domain
        # depending on the context. This domain might filter out some taxes from self, e.g. in the
        # case of group taxes.
        for tax in self.sorted(key=lambda r: r.sequence):
            if tax.amount_type == 'group':
                children = tax.children_tax_ids.with_context(base_values=(total_excluded, total_included, base))
                ret = children.compute_all(price_unit, currency, quantity, product, partner)
                total_excluded = ret['total_excluded']
                base = ret['base'] if tax.include_base_amount else base
                total_included = ret['total_included']
                tax_amount = total_included - total_excluded
                taxes += ret['taxes']
                continue

            tax_amount = tax._compute_amount(base, price_unit, quantity, product, partner)
            if not round_tax:
                tax_amount = round(tax_amount, prec)
            else:
                tax_amount = currency.round(tax_amount)

            if tax.price_include:
                total_excluded -= tax_amount
                base -= tax_amount
            else:
                total_included += tax_amount

            # Keep base amount used for the current tax
            tax_base = base

            if tax.include_base_amount:
                base += tax_amount

            taxes.append({
                'id': tax.id,
                'name': tax.with_context(**{'lang': partner.lang} if partner else {}).name,
                'amount': tax_amount,
                'base': tax_base,
                'sequence': tax.sequence,
                'account_id': tax.account_id.id,
                'refund_account_id': tax.refund_account_id.id,
                'analytic': tax.analytic,
            })

        return {
            'taxes': sorted(taxes, key=lambda k: k['sequence']),
            'total_excluded': currency.round(total_excluded) if round_total else total_excluded,
            'total_included': currency.round(total_included) if round_total else total_included,
            'base': base,
        }
 def _get_invoice_values_odoofact(self):
     if not self.journal_id.edocument_type:
         raise UserError(
             _('Please define Edocument type on the journal related to this invoice.'
               ))
     if not self.journal_id.edocument_type.type_of:
         raise UserError(
             _('Please define the \'Document type\' on the \'Edocument type\' of the journal related to this invoice.'
               ))
     currency = CURRENCY.get(self.currency_id.name, False)
     if not currency:
         raise UserError(
             _('Currency \'%s, %s\' is not available for Electronic invoice. Contact to the Administrator.'
               ) %
             (self.currency_id.name, self.currency_id.currency_unit_label))
     currency_exchange = self.currency_id.with_context(
         date=self.date_invoice)._get_conversion_rate(
             self.currency_id, self.company_id.currency_id,
             self.env.user.company_id, self.date_invoice)
     if currency_exchange == 0:
         raise UserError(
             _('The currency rate should be different to 0.0, Please check the rate at %s'
               ) % self.date_invoice)
     send_email = ''
     if self.shop_id.send_email == True:
         send_email = 'true'
     else:
         send_email = 'false'
     values = {
         'company_id':
         self.company_id.id,
         'shop_id':
         self.shop_id and self.shop_id.id or False,
         'invoice_id':
         self.id,
         "operacion":
         "generar_comprobante",
         'tipo_de_comprobante':
         self.edocument_type.type_of,
         'sunat_transaction':
         int(self.sunat_transaction),
         'serie':
         self.einv_serie,
         'numero':
         str(self.einv_number),
         'cliente_tipo_de_documento':
         self.commercial_partner_id.catalog_06_id
         and self.commercial_partner_id.catalog_06_id.code or '1',
         'cliente_numero_de_documento':
         self.commercial_partner_id.vat and self.commercial_partner_id.vat
         or '00000000',
         'cliente_denominacion':
         self.commercial_partner_id.registration_name
         or self.commercial_partner_id.name,
         'cliente_direccion': (self.commercial_partner_id.street or '') +
         (self.commercial_partner_id.street2 or '') +
         (self.commercial_partner_id.district_id
          and ', ' + self.commercial_partner_id.district_id.name or '') +
         (self.commercial_partner_id.province_id
          and ', ' + self.commercial_partner_id.province_id.name or '') +
         (self.commercial_partner_id.state_id
          and ', ' + self.commercial_partner_id.state_id.name or '') +
         (self.commercial_partner_id.country_id
          and ', ' + self.commercial_partner_id.country_id.name or ''),
         'cliente_email':
         self.commercial_partner_id.email
         and self.commercial_partner_id.email or self.partner_id.email,
         'fecha_de_emision':
         datetime.strptime(str(self.date_invoice),
                           "%Y-%m-%d").strftime("%d-%m-%Y"),
         'fecha_de_vencimiento':
         datetime.strptime(str(self.date_due),
                           "%Y-%m-%d").strftime("%d-%m-%Y"),
         'moneda':
         currency,
         'tipo_de_cambio':
         round(1 / currency_exchange, 3),
         'porcentaje_de_igv':
         self.igv_percent,
         'descuento_global':
         abs(self.global_discount),
         'total_descuento':
         abs(self.amount_discount),
         'total_gravada':
         abs(self.einv_amount_base),
         'total_inafecta':
         abs(self.einv_amount_unaffected),
         'total_exonerada':
         abs(self.einv_amount_exonerated),
         'total_igv':
         abs(self.einv_amount_igv),
         'total_otros_cargos':
         abs(self.einv_amount_others),
         'total':
         abs(self.amount_total),
         'detraccion':
         self.detraction and 'true' or 'false',
         'observaciones':
         self.comment,
         'documento_que_se_modifica_tipo':
         self.origin_document_id and
         (self.origin_document_serie[0] == 'F' and '1' or '2')
         or (self.einv_serie[0] == 'F' and '1' or '2') or '',
         'documento_que_se_modifica_serie':
         self.origin_document_serie or '',
         'documento_que_se_modifica_numero':
         self.origin_document_number or '',
         'tipo_de_nota_de_credito':
         self.credit_note_type and int(self.credit_note_type.code) or '',
         'tipo_de_nota_de_debito':
         self.debit_note_type and int(self.debit_note_type.code) or '',
         'enviar_automaticamente_al_cliente':
         send_email,
         'condiciones_de_pago':
         self.payment_term_id and self.payment_term_id.name or '',
         'items':
         getattr(self, '_get_invoice_line_values_%s' %
                 self._get_ose_supplier())(self.invoice_line_ids),
         'generado_por_contingencia':
         self.is_contingency and 'true' or 'false'
     }
     return values
    def get_cost_perc(self, date_from, date_to, data_from):
        #,data.get('accounts_group_parents')

        sql_query = """


select * ,result.Practical - result.Planned deviation, round( (result.Practical/case when result.Planned = 0 then 1 else result.Planned end)*100    ,2) perc from (


         select
 analytic.code ,
 analytic.name ,

  round(
  (

  case
  when COALESCE(sum(case when type.name = 'Expenses' then amount end),1) = 0 then 1
  else  COALESCE(sum(case when type.name = 'Expenses' then amount end),1) end)*100
  /
  COALESCE(sum(case when type.name = 'Income' then amount end),0)

  ,2) Practical

   ,

(
round(




      case when (( select  COALESCE(sum(case when typesubs.name = 'Expenses' then planned_amount end),0) from
                            crossovered_budget_lines crossbsubs
                             join account_budget_post postsubs on (crossbsubs.general_budget_id = postsubs.id)
                             join account_account accountsubs on (postsubs.account_id = accountsubs.id)
                             join account_account account_parensubst on (accountsubs.parent_id = account_parensubst.id)
                             join account_analytic_account analyticsubs on (crossbsubs.analytic_account_id = analyticsubs.id)
                             join  account_account_type typesubs on (accountsubs.user_type_id = typesubs.id)


                            where analyticsubs.id = analytic.id and analyticsubs.analytic_type = '""" + data_from[
            'analytic_type'] + """' and  date_from between '""" + data_from[
                'start_year_date'] + """-01-01' and '""" + data_from['end_year_date'] + """-12-31'
            ) / 365) * """ + str(data_from['days_days'] + 1) + """ = 0 then 1
else
(( select  COALESCE(sum(case when typesubs.name = 'Expenses' then planned_amount end),0) from
                            crossovered_budget_lines crossbsubs
                             join account_budget_post postsubs on (crossbsubs.general_budget_id = postsubs.id)
                             join account_account accountsubs on (postsubs.account_id = accountsubs.id)
                             join account_account account_parensubst on (accountsubs.parent_id = account_parensubst.id)
                             join account_analytic_account analyticsubs on (crossbsubs.analytic_account_id = analyticsubs.id)
                             join  account_account_type typesubs on (accountsubs.user_type_id = typesubs.id)


                            where analyticsubs.id = analytic.id and analyticsubs.analytic_type = '""" + data_from[
                    'analytic_type'] + """' and  date_from between '""" + data_from[
                        'start_year_date'] + """-01-01' and '""" + data_from[
                            'end_year_date'] + """-12-31'
            ) / 365) * """ + str(data_from['days_days'] + 1) + """

             end
/
           (  (( select  COALESCE(sum(case when typesubs.name = 'Income' then planned_amount end),0) from
                            crossovered_budget_lines crossbsubs
                             join account_budget_post postsubs on (crossbsubs.general_budget_id = postsubs.id)
                             join account_account accountsubs on (postsubs.account_id = accountsubs.id)
                             join account_account account_parensubst on (accountsubs.parent_id = account_parensubst.id)
                             join account_analytic_account analyticsubs on (crossbsubs.analytic_account_id = analyticsubs.id)
                             join  account_account_type typesubs on (accountsubs.user_type_id = typesubs.id)


                            where analyticsubs.id = analytic.id and analyticsubs.analytic_type = '""" + data_from[
                                'analytic_type'] + """' and  date_from between '""" + data_from[
                                    'start_year_date'] + """-01-01' and '""" + data_from[
                                        'end_year_date'] + """-12-31'
            ) / 365) * """ + str(data_from['days_days'] +
                                 1) + """ )


             ,2)* 100 ) Planned






           from account_analytic_line line
             join account_analytic_account analytic on line.account_id = analytic.id
             join account_account account on line.general_account_id = account.id
             join account_account account_parent on (account.parent_id = account_parent.id)
             join  account_account_type type on (account.user_type_id = type.id)

             where account.parent_id in """ + str(
                                     data_from.get('accounts_group_parents')
                                 ).replace("[", "(").replace(
                                     "]", ")"
                                 ) + """ and analytic.analytic_type = '""" + data_from[
                                     'analytic_type'] + """'
              and date between '""" + date_from + """' and '""" + date_to + """' group by analytic.id order by analytic.code
        ) result """
        #print(">>>>>>>>>>>>>>>>>>>>>>>get_cost_perc ",sql_query)

        # exceute query
        self._cr.execute(sql_query)

        # return result
        return self._cr.dictfetchall()
    def get_parents_analytics_net(self, date_from, date_to, parents_id,
                                  data_from):
        """
        Desc : Get all budget analytic accounts related to parent account
        :param date_from:
        :param date_to:
        :param parents_id:
        :return:
        """
        # parent query

        if len(parents_id) == 1:
            parents_id = str(parents_id).replace(',', '')

        sql_query = """


select
                 analytic.id ,
                 analytic.code ,
                 analytic.name ,
                 sum(amount)  practical ,

                 round((( select  sum(planned_amount) from
                crossovered_budget_lines crossbsubs
                 join account_budget_post postsubs on (crossbsubs.general_budget_id = postsubs.id)
                 join account_account accountsubs on (postsubs.account_id = accountsubs.id)
                 join account_account account_parensubst on (accountsubs.parent_id = account_parensubst.id)
                 join account_analytic_account analyticsubs on (crossbsubs.analytic_account_id = analyticsubs.id)


                where analyticsubs.id = analytic.id and analyticsubs.analytic_type = '""" + data_from[
            'analytic_type'] + """' and date_from between '""" + data_from[
                'start_year_date'] + """-01-01' and '""" + data_from[
                    'end_year_date'] + """-12-31'
) / 365) * """ + str(data_from['days_days'] + 1) + """,2)  planned_amount  ,
 sum(amount) -
round(
(( select  sum(planned_amount) from
                crossovered_budget_lines crossbsubs
                 join account_budget_post postsubs on (crossbsubs.general_budget_id = postsubs.id)
                 join account_account accountsubs on (postsubs.account_id = accountsubs.id)
                 join account_account account_parensubst on (accountsubs.parent_id = account_parensubst.id)
                 join account_analytic_account analyticsubs on (crossbsubs.analytic_account_id = analyticsubs.id)


                where analyticsubs.id = analytic.id and analyticsubs.analytic_type = '""" + data_from[
                        'analytic_type'] + """' and date_from between '""" + data_from[
                            'start_year_date'] + """-01-01' and '""" + data_from[
                                'end_year_date'] + """-12-31'
) / 365 * """ + str(data_from['days_days'] +
                    1) + """),2) deviation ,


round((sum(amount) /

((( select  sum(planned_amount) from
                crossovered_budget_lines crossbsubs
                 join account_budget_post postsubs on (crossbsubs.general_budget_id = postsubs.id)
                 join account_account accountsubs on (postsubs.account_id = accountsubs.id)
                 join account_account account_parensubst on (accountsubs.parent_id = account_parensubst.id)
                 join account_analytic_account analyticsubs on (crossbsubs.analytic_account_id = analyticsubs.id)


                where analyticsubs.id = analytic.id and analyticsubs.analytic_type = '""" + data_from[
                        'analytic_type'] + """' and date_from between '""" + data_from[
                            'start_year_date'] + """-01-01' and '""" + data_from[
                                'end_year_date'] + """-12-31'
) / 365) * """ + str(data_from['days_days'] +
                     1) + """))*100,2) percentage



from account_analytic_line line
 join account_analytic_account analytic on line.account_id = analytic.id
 join account_account account on line.general_account_id = account.id
 join account_account account_parent on (account.parent_id = account_parent.id)

 where account.parent_id in """ + str(
                         parents_id
                     ) + """ and analytic.analytic_type = '""" + data_from[
                         'analytic_type'] + """' and
 date between '""" + date_from + """' and '""" + date_to + """'  group by analytic.id order by analytic.code

    """
        #print(">>>>>>>>>>>>>>>>>>>>>>>>>>NEW QUERY ",sql_query)

        # exceute query
        self._cr.execute(sql_query)

        # return result
        return self._cr.dictfetchall()
Exemple #28
0
    def compute_all(self, price_unit, currency=None, quantity=1.0, product=None, partner=None):
        """ Returns all information required to apply taxes (in self + their children in case of a tax goup).
            We consider the sequence of the parent for group of taxes.
                Eg. considering letters as taxes and alphabetic order as sequence :
                [G, B([A, D, F]), E, C] will be computed as [A, D, F, C, E, G]

        RETURN: {
            'total_excluded': 0.0,    # Total without taxes
            'total_included': 0.0,    # Total with taxes
            'taxes': [{               # One dict for each tax in self and their children
                'id': int,
                'name': str,
                'amount': float,
                'sequence': int,
                'account_id': int,
                'refund_account_id': int,
                'analytic': boolean,
            }]
        } """
        if len(self) == 0:
            company_id = self.env.user.company_id
        else:
            company_id = self[0].company_id
        if not currency:
            currency = company_id.currency_id
        taxes = []
        # By default, for each tax, tax amount will first be computed
        # and rounded at the 'Account' decimal precision for each
        # PO/SO/invoice line and then these rounded amounts will be
        # summed, leading to the total amount for that tax. But, if the
        # company has tax_calculation_rounding_method = round_globally,
        # we still follow the same method, but we use a much larger
        # precision when we round the tax amount for each line (we use
        # the 'Account' decimal precision + 5), and that way it's like
        # rounding after the sum of the tax amounts of each line
        prec = currency.decimal_places

        # In some cases, it is necessary to force/prevent the rounding of the tax and the total
        # amounts. For example, in SO/PO line, we don't want to round the price unit at the
        # precision of the currency.
        # The context key 'round' allows to force the standard behavior.
        round_tax = False if company_id.tax_calculation_rounding_method == 'round_globally' else True
        round_total = True
        if 'round' in self.env.context:
            round_tax = bool(self.env.context['round'])
            round_total = bool(self.env.context['round'])

        if not round_tax:
            prec += 5

        base_values = self.env.context.get('base_values')
        if not base_values:
            total_excluded = total_included = base = round(price_unit * quantity, prec)
        else:
            total_excluded, total_included, base = base_values

        # Sorting key is mandatory in this case. When no key is provided, sorted() will perform a
        # search. However, the search method is overridden in account.tax in order to add a domain
        # depending on the context. This domain might filter out some taxes from self, e.g. in the
        # case of group taxes.
        for tax in self.sorted(key=lambda r: r.sequence):
            if tax.amount_type == 'group':
                children = tax.children_tax_ids.with_context(base_values=(total_excluded, total_included, base))
                ret = children.compute_all(price_unit, currency, quantity, product, partner)
                total_excluded = ret['total_excluded']
                base = ret['base'] if tax.include_base_amount else base
                total_included = ret['total_included']
                tax_amount = total_included - total_excluded
                taxes += ret['taxes']
                continue

            tax_amount = tax._compute_amount(base, price_unit, quantity, product, partner)
            if not round_tax:
                tax_amount = round(tax_amount, prec)
            else:
                tax_amount = currency.round(tax_amount)

            if tax.price_include:
                total_excluded -= tax_amount
                base -= tax_amount
            else:
                total_included += tax_amount

            # Keep base amount used for the current tax
            tax_base = base

            if tax.include_base_amount:
                base += tax_amount

            taxes.append({
                'id': tax.id,
                'name': tax.with_context(**{'lang': partner.lang} if partner else {}).name,
                'amount': tax_amount,
                'base': tax_base,
                'sequence': tax.sequence,
                'account_id': tax.account_id.id,
                'refund_account_id': tax.refund_account_id.id,
                'analytic': tax.analytic,
            })

        return {
            'taxes': sorted(taxes, key=lambda k: k['sequence']),
            'total_excluded': currency.round(total_excluded) if round_total else total_excluded,
            'total_included': currency.round(total_included) if round_total else total_included,
            'base': base,
        }
    def print_report(self):
        """
        Print Analytic Budget Report Based on User Choices
        :return:
        """

        # Check if date from grater than date to
        if self.date_from > self.date_to:
            raise ValidationError(
                _("""You Must Set 'Date From' less Than 'Date To'."""))

        # set start up parameters
        params = [
            ('account_id.analytic_type', '=', self.analytic_type),
            ('date', '>=', self.date_from),
            ('date', '<=', self.date_to),
        ]

        # get first day of the year
        start_year_date = self.date_from[0:4]
        # get last day of the year
        end_year_date = self.date_to[0:4]

        if start_year_date != end_year_date:
            raise UserError(
                _("Plz , You must select two dates in the same year!"))

        # if user choose type analytic and select an analytic account then add ot to parameters
        if self.report_type == 'analytic' and self.analytic_account_id:
            params.append(('account_id', '=', self.analytic_account_id.id))

        # search
        budget_lines = self.env['account.analytic.line'].search(params)

        # if no data then raise exception to user
        if len(budget_lines) == 0:
            raise UserError(_("No Budget Data To Print!!"))

        # get all main parents accounts only
        accounts_parents = [
            line.general_account_id.parent_id.id for line in budget_lines
        ]

        # get unique parents
        accounts_parents = tuple(set(accounts_parents))

        # to avoid comma that will trigger sql syntax error in query
        if len(accounts_parents) == 1:
            accounts_parents = str(accounts_parents).replace(",", "")

        # init data
        data = {}

        # get first day of year
        start_year_date = self.date_from[0:4]
        # get last day of year
        end_year_date = self.date_to[0:4]

        date_format = "%Y-%m-%d"
        start = datetime.strptime(self.date_from, date_format)
        end = datetime.strptime(self.date_to, date_format)
        days = end - start

        #print(">>>>>>>>>>>>>>>>>>>>>>>>>>DATE", (days.days + 1))

        # parent query
        sql_query = """
                select
                 account_parent.id ,
                 account_parent.code ,
                 account_parent.name ,
                 sum(amount)  practical ,

                 round((( select  sum(planned_amount) from
                crossovered_budget_lines crossbsubs
                 join account_budget_post postsubs on (crossbsubs.general_budget_id = postsubs.id)
                 join account_account accountsubs on (postsubs.account_id = accountsubs.id)
                 join account_account account_parensubst on (accountsubs.parent_id = account_parensubst.id)
                 join account_analytic_account analyticsubs on (crossbsubs.analytic_account_id = analyticsubs.id)
                 

                where accountsubs.parent_id = account_parent.id and analyticsubs.analytic_type = '""" + self.analytic_type + """' and date_from between '""" + start_year_date + """-01-01' and '""" + end_year_date + """-12-31'
) / 365) * """ + str(days.days + 1) + """,2)  planned_amount  ,
sum(amount) -
round(
(( select  sum(planned_amount) from
                crossovered_budget_lines crossbsubs
                 join account_budget_post postsubs on (crossbsubs.general_budget_id = postsubs.id)
                 join account_account accountsubs on (postsubs.account_id = accountsubs.id)
                 join account_account account_parensubst on (accountsubs.parent_id = account_parensubst.id)
                 join account_analytic_account analyticsubs on (crossbsubs.analytic_account_id = analyticsubs.id)
                 

                where accountsubs.parent_id = account_parent.id and analyticsubs.analytic_type = '""" + self.analytic_type + """' and date_from between '""" + start_year_date + """-01-01' and '""" + end_year_date + """-12-31'
) / 365 * """ + str(days.days + 1) + """),2) deviation ,


round((sum(amount) /

((( select  sum(planned_amount) from
                crossovered_budget_lines crossbsubs
                 join account_budget_post postsubs on (crossbsubs.general_budget_id = postsubs.id)
                 join account_account accountsubs on (postsubs.account_id = accountsubs.id)
                 join account_account account_parensubst on (accountsubs.parent_id = account_parensubst.id)
                 join account_analytic_account analyticsubs on (crossbsubs.analytic_account_id = analyticsubs.id)
                 

                where accountsubs.parent_id = account_parent.id and analyticsubs.analytic_type = '""" + self.analytic_type + """' and date_from between '""" + start_year_date + """-01-01' and '""" + end_year_date + """-12-31'
) / 365) * """ + str(days.days + 1) + """))*100,2) percentage



from account_analytic_line line
 join account_analytic_account analytic on line.account_id = analytic.id
 join account_account account on line.general_account_id = account.id
 join account_account account_parent on (account.parent_id = account_parent.id)

 where account.parent_id in """ + str(
            accounts_parents
        ) + """   and analytic.analytic_type = '""" + self.analytic_type + """'  and
 date between '""" + self.date_from + """' and '""" + self.date_to + """'  group by account_parent.id

                 """

        data.update({'report_type': self.report_type})
        # if we not add new report type then the following if is useless
        #if self.report_type in ('analytic', 'summation'):
        # Execute Query
        self._cr.execute(sql_query)

        # get Query Result and save it in data 'parents_query_result'
        data.update({'parents_query_result': self._cr.dictfetchall()})

        data.update({'date_from': self.date_from})
        data.update({'date_to': self.date_to})
        data.update({'report_type': self.report_type})

        data.update({'analytic_type': self.analytic_type})
        data.update({'analytic_account': self.analytic_account_id.name})
        data.update({'show_up_totals': self.show_up_totals})
        data.update({'start_year_date': start_year_date})
        data.update({'end_year_date': end_year_date})
        data.update({'days_days': days.days})

        if self.group_totals == True:
            #print("!!!!!!!! >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> !!!!!!!!!")

            type_sql_query = """
                            select type.id type_id,
                             'Total Of '|| type.name account_name ,
                             sum(amount)  practical ,

                             round((( select  sum(planned_amount) from
                            crossovered_budget_lines crossbsubs
                             join account_budget_post postsubs on (crossbsubs.general_budget_id = postsubs.id)
                             join account_account accountsubs on (postsubs.account_id = accountsubs.id)
                             join account_account account_parensubst on (accountsubs.parent_id = account_parensubst.id)
                             join account_analytic_account analyticsubs on (crossbsubs.analytic_account_id = analyticsubs.id)
                             join  account_account_type typesubs on (accountsubs.user_type_id = typesubs.id)


                            where typesubs.id = type.id and analyticsubs.analytic_type = '""" + self.analytic_type + """' and  date_from between '""" + start_year_date + """-01-01' and '""" + end_year_date + """-12-31'
            ) / 365) * """ + str(days.days + 1) + """,2)  planned_amount  ,
            sum(amount) -
            round(
            (( select  sum(planned_amount) from
                            crossovered_budget_lines crossbsubs
                             join account_budget_post postsubs on (crossbsubs.general_budget_id = postsubs.id)
                             join account_account accountsubs on (postsubs.account_id = accountsubs.id)
                             join account_account account_parensubst on (accountsubs.parent_id = account_parensubst.id)
                             join account_analytic_account analyticsubs on (crossbsubs.analytic_account_id = analyticsubs.id)
                             join  account_account_type typesubs on (accountsubs.user_type_id = typesubs.id)


                            where typesubs.id = type.id and analyticsubs.analytic_type = '""" + self.analytic_type + """' and date_from between '""" + start_year_date + """-01-01' and '""" + end_year_date + """-12-31'
            ) / 365 * """ + str(days.days + 1) + """),2) deviation ,


            round((sum(amount) /

            ((( select  sum(planned_amount) from
                            crossovered_budget_lines crossbsubs
                             join account_budget_post postsubs on (crossbsubs.general_budget_id = postsubs.id)
                             join account_account accountsubs on (postsubs.account_id = accountsubs.id)
                             join account_account account_parensubst on (accountsubs.parent_id = account_parensubst.id)
                             join account_analytic_account analyticsubs on (crossbsubs.analytic_account_id = analyticsubs.id)
                             join  account_account_type typesubs on (accountsubs.user_type_id = typesubs.id)


                            where typesubs.id = type.id and analyticsubs.analytic_type = '""" + self.analytic_type + """' and date_from between '""" + start_year_date + """-01-01' and '""" + end_year_date + """-12-31'
            ) / 365) * """ + str(days.days + 1) + """))*100,2) percentage



            from account_analytic_line line
             join account_analytic_account analytic on line.account_id = analytic.id
             join account_account account on line.general_account_id = account.id
             join account_account account_parent on (account.parent_id = account_parent.id)
             join  account_account_type type on (account.user_type_id = type.id)

             where account.parent_id in """ + str(
                accounts_parents
            ) + """ and analytic.analytic_type = '""" + self.analytic_type + """' and
             date between '""" + self.date_from + """' and '""" + self.date_to + """'  group by type.id ORDER BY type.name

                             """

            #print(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>type_sql_query ",type_sql_query)

            self._cr.execute(type_sql_query)
            data.update({'type_query_result': self._cr.dictfetchall()})
            data.update({'group_totals': self.group_totals})
            data.update({'accounts_group_parents': accounts_parents})
            #data.update({'group_totals_result_count': len(data['type_query_result'])})

            #print(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>QROUP TOTALS ",len(data['type_query_result']))

        if self.show_net_other_income == True:
            net_other_income_query = """

            select sum(debit-credit)
from account_move_line line
join account_account account on line.account_id = account.id
join account_account_type  type on account.user_type_id = type.id
join account_move move on line.move_id = move.id

where type.name = 'Other Income' and line.date <= '""" + self.date_to + """' and move.state = 'posted'"""
            #print(">>>>>>>>>>>>>>>>>>>>>QUERY ",net_other_income_query)
            self._cr.execute(net_other_income_query)
            result = self._cr.dictfetchall()

            if result[0]['sum'] != None:
                data.update(
                    {'net_other_income_query_result': result[0]['sum']})

            else:
                data.update({'net_other_income_query_result': 0})

            data.update({'show_net_other_income': self.show_net_other_income})

        return self.env.ref(
            'account_budget_custom.action_analytic_budget_report'
        ).with_context(landscape=True).report_action(self, data=data)
Exemple #30
0
    def render_html(self, docids, data=None):
        report_obj = self.env['report']
        report = report_obj._get_report_from_name('puntoingreso.report_estudios_data')


        pacientes = self.env['puntoingreso.service'].search([('id', 'in', docids)], order="patient_ids").mapped('patient_ids')

        fechas = []
        resumen = []
        estudio_paciente = []
        gastos = []
        honors = []
        gastos_por = 0
        honors_por = 0
        tarifa = 0
        osocial = ''
        gastos_prom = 0
        honors_prom = 0
        # total_h_paciente = 0
        # total_g_paciente = 0


        for est in pacientes:

            servicios = self.env['puntoingreso.service'].search([('id', 'in', docids), ('patient_ids', '=', est.id)], order="patient_ids")
            _logger.info('servicios_2do')
            _logger.info(servicios)

            ptg = 0
            pth = 0
            paciente = servicios[0].patient_ids.name

            _logger.info('paciente')
            _logger.info(paciente)
            _logger.info('cambia')

            for serv in servicios:

                p_g = self.env['puntoingreso.service'].search([('id', 'in', docids), ('patient_ids', '=', serv.patient_ids.id)])

                _logger.info('p_g_estudios_tildados_paciente')
                _logger.info(p_g)

                for p in p_g:
                    ptg = ptg + p.costos
                    # _logger.info(ptg)
                    pth = pth + p.galeno
                    # _logger.info(pth)

                # total_g_paciente = ptg
                # total_h_paciente = pth
                # _logger.info('total_g_paciente')
                # _logger.info(total_g_paciente)
                # _logger.info('total_h_paciente')
                # _logger.info(total_h_paciente)



                if serv.variant_id.inc_subservicio and not serv.modulada:
                    _logger.info('incluye_subservicios')
                    osocial = serv.osocial
                    subservis = self.env['product.product'].search([('parent_id', '=', serv.variant_id.id)])
                    _logger.info(subservis)

                    for ss in subservis:

                        date_nueva = serv.input_date
                        date_nueva = date_nueva.split('-')
                        date_final = "%s/%s/%s" % (date_nueva[2], date_nueva[1], date_nueva[0])

                        ss_final = dict({
                            'center': serv._get_string_from_selection(),
                            'codigo_servicio': '-',
                            'doctor_ids': serv.doctor_ids,
                            'patient_ids': serv.patient_ids,
                            'n_afiliado': serv.n_afiliado,
                            'input_date': date_final,
                            'variant_id': 0,
                            'service_id': 0,
                            'costos': 0,
                            'galeno': 0,
                            'tarifa': 0,
                            'total_g': 0,
                            'total_h': 0,
                            'total_t': 0
                            })

                        # traemos logica de estudios.py
                        lista_precio_obrasocial = self.env['res.partner'].search([('name', '=', osocial.name),('x_is_osocial','=', True)]).property_product_pricelist.id

                        n_tarifa = None

                        tarifa_estudio = self.env['product.pricelist.item'].search([('pricelist_id', '=', lista_precio_obrasocial),('product_id', '=', ss.id)])

                        agregar = True

                        if tarifa_estudio:
                            for x in tarifa_estudio:
                                if (x.date_start != False and x.date_end != False and x.date_start <= serv.input_date and x.date_end >= serv.input_date) or (x.date_end != False and x.date_end >= serv.input_date and x.date_start == False) or (x.date_start != False and x.date_start <= serv.input_date and x.date_end == False) or (x.date_start == False and x.date_end == False):

                                    n_tarifa = x.id
                                    fecha_inicio = x.date_start
                                    fecha_fin = x.date_end
                                    honor = x.min_quantity
                                    costo = x.costo

                        if n_tarifa is None:
                            fecha_inicio = None
                            fecha_fin = None
                            honor = 0
                            costo = 0

                            #costos
                            ss_final['costos'] = 0
                            ss_final['galeno'] = 0
                            ss_final['tarifa'] = 0
                            agregar = False

                        else:
                            fecha_inicio = self.env['product.pricelist.item'].search([('pricelist_id', '=', lista_precio_obrasocial),('product_id', '=', ss.id),('id','=',n_tarifa)]).date_start


                            fecha_fin = self.env['product.pricelist.item'].search([('pricelist_id', '=', lista_precio_obrasocial),('product_id', '=', ss.id),('id','=',n_tarifa)]).date_end


                            honor = self.env['product.pricelist.item'].search([('pricelist_id', '=', lista_precio_obrasocial),('product_id', '=', ss.id),('id','=',n_tarifa)]).min_quantity

                            costo = self.env['product.pricelist.item'].search([('pricelist_id', '=', lista_precio_obrasocial),('product_id', '=', ss.id),('id','=',n_tarifa)]).costo

                            t_modulada = self.env['product.pricelist.item'].search([('pricelist_id', '=', lista_precio_obrasocial),('product_id', '=', ss.id),('id','=',n_tarifa)]).modulada

                            codigo_servicio = self.env['product.pricelist.item'].search([('pricelist_id', '=', lista_precio_obrasocial),('product_id', '=', ss.id),('id','=',n_tarifa)]).codigo_servicio

                            _logger.info('codigo_sservicio')
                            _logger.info(codigo_servicio)

                            ss_final['codigo_servicio'] = codigo_servicio

                            if t_modulada:

                                tarifa_total = costo
                                costo_total = costo
                                honor_total = 0

                                #costos
                                ss_final['costos'] = costo_total
                                ss_final['galeno'] = honor_total
                                ss_final['tarifa'] = tarifa_total

                            else:
                                #sino todo como estaba
                                multi_costo = self.env['product.template'].browse(ss.product_tmpl_id.id).multi_costo
                                multi_honor = self.env['product.template'].browse(ss.product_tmpl_id.id).multi_honor

                                costo_total = multi_costo * costo
                                honor_total = multi_honor * honor

                                tarifa_total =  costo_total + honor_total

                                #costos
                                ss_final['costos'] = costo_total
                                ss_final['galeno'] = honor_total
                                ss_final['tarifa'] = tarifa_total


                        #datos generales
                        ss_final['service_id'] = ss.product_tmpl_id
                        ss_final['variant_id'] = ss

                        # ss_final['total_g'] = costo_total
                        # ss_final['total_h'] = honor_total
                        # ss_final['total_t'] = tarifa_total

                        _logger.info('ss_final')
                        _logger.info(ss_final)


                        gastos.append(ss_final['costos'])
                        honors.append(ss_final['galeno'])

                        if agregar:
                            estudio_paciente.append(ss_final)

                            resu_add = [ss_final['codigo_servicio'],ss_final['variant_id'].name,1,ss_final['tarifa']]

                            if resu_add not in resumen:
                                resumen.append(resu_add)
                            else:
                                for re in resumen:
                                    if re == resu_add:
                                        re[2] += 1


                        if date_final not in fechas:
                            fechas.append(date_final)


                else:
                    _logger.info('NO_incluye_subservicios')

                    date_nueva = serv.input_date
                    date_nueva = date_nueva.split('-')
                    date_final = "%s/%s/%s" % (date_nueva[2], date_nueva[1], date_nueva[0])

                    serv.total_g = ptg
                    serv.total_h = pth
                    serv.total_t = pth + ptg
                    _logger.info(ptg)
                    _logger.info(pth)
                    _logger.info(pth + ptg)

                    gastos.append(serv.costos)
                    honors.append(serv.galeno)
                    tarifa = serv.tarifa
                    osocial = serv.osocial

                    gastos_prom = gastos_prom+serv.costos
                    honors_prom = honors_prom+serv.galeno

                    _logger.info('mismo')
                    _logger.info(serv)
                    _logger.info(serv.service_id.display_name)

                    ss_final = dict({
                        'center': serv._get_string_from_selection(),
                        'codigo_servicio': serv.codigo_servicio,
                        'doctor_ids': serv.doctor_ids,
                        'patient_ids': serv.patient_ids,
                        'n_afiliado': serv.n_afiliado,
                        'variant_id': serv.variant_id,
                        'service_id': serv.service_id,
                        'input_date': date_final,
                        'costos': serv.costos,
                        'galeno': serv.galeno,
                        'tarifa': serv.tarifa,
                        'total_g': ptg,
                        'total_h': pth,
                        'total_t': (pth + ptg)
                        })

                    #estudio_paciente.append(serv)
                    resu_add = [ss_final['codigo_servicio'],ss_final['variant_id'].name,1,ss_final['tarifa']]
                    if resu_add not in resumen:
                        resumen.append(resu_add)
                    else:
                        for re in resumen:
                            if re == resu_add:
                                re[2] += 1


                    estudio_paciente.append(ss_final)
                    if date_final not in fechas:
                            fechas.append(date_final)

            #estudio_paciente.append(servicios)
            #estudio_paciente.append(serv)

        _logger.info('estudios_paciente')
        _logger.info(estudio_paciente)


        total_total = gastos_prom + honors_prom

        if total_total != 0:
            gastos_por = (gastos_prom * 100) / total_total
            honors_por = (honors_prom * 100) / total_total
        else:
            gastos_por = 0
            honors_por = 0

        #Redondeo a 2 decimales de porcentaje
        gastos_por = math.ceil(gastos_por*100)/100
        honors_por = math.ceil(honors_por*100)/100



        gastos_prom = gastos_prom / len(gastos)
        honors_prom = honors_prom / len(honors)

        #Redondeo a 2 decimales de promedio
        # gastos_prom = math.ceil(gastos_prom*100)/100
        # honors_prom = math.ceil(honors_prom*100)/100
        gastos_prom = round(gastos_prom,2)
        honors_prom = round(honors_prom,2)


        docargs = {
            'fechas': fechas,
            'doc_model': report.model,
            'docs_p': estudio_paciente,
            'osocial': osocial.display_name,
            'resumen': resumen,
            #'docs': pacientes,
            #'doc_ids': docids,
            #'gastos_prom': gastos_prom,
            #'honors_prom': honors_prom,
            #'gastos_por': gastos_por,
            #'honors_por': honors_por,
        }
        return report_obj.render('puntoingreso.report_estudios_data', docargs)
Exemple #31
0
    def compute_all(self,
                    price_unit,
                    currency=None,
                    quantity=1.0,
                    product=None,
                    partner=None,
                    is_refund=False,
                    handle_price_include=True,
                    include_caba_tags=False):
        """ Returns all information required to apply taxes (in self + their children in case of a tax group).
            We consider the sequence of the parent for group of taxes.
                Eg. considering letters as taxes and alphabetic order as sequence :
                [G, B([A, D, F]), E, C] will be computed as [A, D, F, C, E, G]

            'handle_price_include' is used when we need to ignore all tax included in price. If False, it means the
            amount passed to this method will be considered as the base of all computations.

        RETURN: {
            'total_excluded': 0.0,    # Total without taxes
            'total_included': 0.0,    # Total with taxes
            'total_void'    : 0.0,    # Total with those taxes, that don't have an account set
            'taxes': [{               # One dict for each tax in self and their children
                'id': int,
                'name': str,
                'amount': float,
                'sequence': int,
                'account_id': int,
                'refund_account_id': int,
                'analytic': boolean,
            }],
        } """
        if not self:
            company = self.env.company
        else:
            company = self[0].company_id

        # 1) Flatten the taxes.
        taxes, groups_map = self.flatten_taxes_hierarchy(create_map=True)

        # 2) Deal with the rounding methods
        if not currency:
            currency = company.currency_id

        # By default, for each tax, tax amount will first be computed
        # and rounded at the 'Account' decimal precision for each
        # PO/SO/invoice line and then these rounded amounts will be
        # summed, leading to the total amount for that tax. But, if the
        # company has tax_calculation_rounding_method = round_globally,
        # we still follow the same method, but we use a much larger
        # precision when we round the tax amount for each line (we use
        # the 'Account' decimal precision + 5), and that way it's like
        # rounding after the sum of the tax amounts of each line
        prec = currency.rounding

        # In some cases, it is necessary to force/prevent the rounding of the tax and the total
        # amounts. For example, in SO/PO line, we don't want to round the price unit at the
        # precision of the currency.
        # The context key 'round' allows to force the standard behavior.
        round_tax = False if company.tax_calculation_rounding_method == 'round_globally' else True
        if 'round' in self.env.context:
            round_tax = bool(self.env.context['round'])

        if not round_tax:
            prec *= 1e-5

        # 3) Iterate the taxes in the reversed sequence order to retrieve the initial base of the computation.
        #     tax  |  base  |  amount  |
        # /\ ----------------------------
        # || tax_1 |  XXXX  |          | <- we are looking for that, it's the total_excluded
        # || tax_2 |   ..   |          |
        # || tax_3 |   ..   |          |
        # ||  ...  |   ..   |    ..    |
        #    ----------------------------
        def recompute_base(base_amount, fixed_amount, percent_amount,
                           division_amount):
            # Recompute the new base amount based on included fixed/percent amounts and the current base amount.
            # Example:
            #  tax  |  amount  |   type   |  price_include  |
            # -----------------------------------------------
            # tax_1 |   10%    | percent  |  t
            # tax_2 |   15     |   fix    |  t
            # tax_3 |   20%    | percent  |  t
            # tax_4 |   10%    | division |  t
            # -----------------------------------------------

            # if base_amount = 145, the new base is computed as:
            # (145 - 15) / (1.0 + 30%) * 90% = 130 / 1.3 * 90% = 90
            return (base_amount - fixed_amount) / (
                1.0 + percent_amount / 100.0) * (100 - division_amount) / 100

        # The first/last base must absolutely be rounded to work in round globally.
        # Indeed, the sum of all taxes ('taxes' key in the result dictionary) must be strictly equals to
        # 'price_included' - 'price_excluded' whatever the rounding method.
        #
        # Example using the global rounding without any decimals:
        # Suppose two invoice lines: 27000 and 10920, both having a 19% price included tax.
        #
        #                   Line 1                      Line 2
        # -----------------------------------------------------------------------
        # total_included:   27000                       10920
        # tax:              27000 / 1.19 = 4310.924     10920 / 1.19 = 1743.529
        # total_excluded:   22689.076                   9176.471
        #
        # If the rounding of the total_excluded isn't made at the end, it could lead to some rounding issues
        # when summing the tax amounts, e.g. on invoices.
        # In that case:
        #  - amount_untaxed will be 22689 + 9176 = 31865
        #  - amount_tax will be 4310.924 + 1743.529 = 6054.453 ~ 6054
        #  - amount_total will be 31865 + 6054 = 37919 != 37920 = 27000 + 10920
        #
        # By performing a rounding at the end to compute the price_excluded amount, the amount_tax will be strictly
        # equals to 'price_included' - 'price_excluded' after rounding and then:
        #   Line 1: sum(taxes) = 27000 - 22689 = 4311
        #   Line 2: sum(taxes) = 10920 - 2176 = 8744
        #   amount_tax = 4311 + 8744 = 13055
        #   amount_total = 31865 + 13055 = 37920
        base = currency.round(price_unit * quantity)

        # For the computation of move lines, we could have a negative base value.
        # In this case, compute all with positive values and negate them at the end.
        sign = 1
        if currency.is_zero(base):
            sign = self._context.get('force_sign', 1)
        elif base < 0:
            sign = -1
        if base < 0:
            base = -base

        # Store the totals to reach when using price_include taxes (only the last price included in row)
        total_included_checkpoints = {}
        i = len(taxes) - 1
        store_included_tax_total = True
        # Keep track of the accumulated included fixed/percent amount.
        incl_fixed_amount = incl_percent_amount = incl_division_amount = 0
        # Store the tax amounts we compute while searching for the total_excluded
        cached_tax_amounts = {}
        if handle_price_include:
            for tax in reversed(taxes):
                tax_repartition_lines = (
                    is_refund and tax.refund_repartition_line_ids
                    or tax.invoice_repartition_line_ids
                ).filtered(lambda x: x.repartition_type == "tax")
                sum_repartition_factor = sum(
                    tax_repartition_lines.mapped("factor"))

                if tax.include_base_amount:
                    base = recompute_base(base, incl_fixed_amount,
                                          incl_percent_amount,
                                          incl_division_amount)
                    incl_fixed_amount = incl_percent_amount = incl_division_amount = 0
                    store_included_tax_total = True
                if tax.price_include or self._context.get(
                        'force_price_include'):
                    if tax.amount_type == 'percent':
                        incl_percent_amount += tax.amount * sum_repartition_factor
                    elif tax.amount_type == 'division':
                        incl_division_amount += tax.amount * sum_repartition_factor
                    elif tax.amount_type == 'fixed':
                        incl_fixed_amount += abs(
                            quantity) * tax.amount * sum_repartition_factor
                    else:
                        # tax.amount_type == other (python)
                        tax_amount = tax._compute_amount(
                            base, sign * price_unit, quantity, product,
                            partner) * sum_repartition_factor
                        incl_fixed_amount += tax_amount
                        # Avoid unecessary re-computation
                        cached_tax_amounts[i] = tax_amount
                    # In case of a zero tax, do not store the base amount since the tax amount will
                    # be zero anyway. Group and Python taxes have an amount of zero, so do not take
                    # them into account.
                    if store_included_tax_total and (
                            tax.amount or tax.amount_type
                            not in ("percent", "division", "fixed")):
                        total_included_checkpoints[i] = base
                        store_included_tax_total = False
                i -= 1

        total_excluded = currency.round(
            recompute_base(base, incl_fixed_amount, incl_percent_amount,
                           incl_division_amount))

        # 4) Iterate the taxes in the sequence order to compute missing tax amounts.
        # Start the computation of accumulated amounts at the total_excluded value.
        base = total_included = total_void = total_excluded

        # Flag indicating the checkpoint used in price_include to avoid rounding issue must be skipped since the base
        # amount has changed because we are currently mixing price-included and price-excluded include_base_amount
        # taxes.
        skip_checkpoint = False

        # Get product tags, account.account.tag objects that need to be injected in all
        # the tax_tag_ids of all the move lines created by the compute all for this product.
        product_tag_ids = product.account_tag_ids.ids if product else []

        taxes_vals = []
        i = 0
        cumulated_tax_included_amount = 0
        for tax in taxes:
            price_include = self._context.get('force_price_include',
                                              tax.price_include)

            if price_include or tax.is_base_affected:
                tax_base_amount = base
            else:
                tax_base_amount = total_excluded

            tax_repartition_lines = (
                is_refund and tax.refund_repartition_line_ids
                or tax.invoice_repartition_line_ids
            ).filtered(lambda x: x.repartition_type == 'tax')
            sum_repartition_factor = sum(
                tax_repartition_lines.mapped('factor'))

            #compute the tax_amount
            if not skip_checkpoint and price_include and total_included_checkpoints.get(
                    i) and sum_repartition_factor != 0:
                # We know the total to reach for that tax, so we make a substraction to avoid any rounding issues
                tax_amount = total_included_checkpoints[i] - (
                    base + cumulated_tax_included_amount)
                cumulated_tax_included_amount = 0
            else:
                tax_amount = tax.with_context(
                    force_price_include=False)._compute_amount(
                        tax_base_amount, sign * price_unit, quantity, product,
                        partner)

            # Round the tax_amount multiplied by the computed repartition lines factor.
            tax_amount = round(tax_amount, precision_rounding=prec)
            factorized_tax_amount = round(tax_amount * sum_repartition_factor,
                                          precision_rounding=prec)

            if price_include and not total_included_checkpoints.get(i):
                cumulated_tax_included_amount += factorized_tax_amount

            # If the tax affects the base of subsequent taxes, its tax move lines must
            # receive the base tags and tag_ids of these taxes, so that the tax report computes
            # the right total
            subsequent_taxes = self.env['account.tax']
            subsequent_tags = self.env['account.account.tag']
            if tax.include_base_amount:
                subsequent_taxes = taxes[i + 1:].filtered('is_base_affected')

                taxes_for_subsequent_tags = subsequent_taxes

                if not include_caba_tags:
                    taxes_for_subsequent_tags = subsequent_taxes.filtered(
                        lambda x: x.tax_exigibility != 'on_payment')

                subsequent_tags = taxes_for_subsequent_tags.get_tax_tags(
                    is_refund, 'base')

            # Compute the tax line amounts by multiplying each factor with the tax amount.
            # Then, spread the tax rounding to ensure the consistency of each line independently with the factorized
            # amount. E.g:
            #
            # Suppose a tax having 4 x 50% repartition line applied on a tax amount of 0.03 with 2 decimal places.
            # The factorized_tax_amount will be 0.06 (200% x 0.03). However, each line taken independently will compute
            # 50% * 0.03 = 0.01 with rounding. It means there is 0.06 - 0.04 = 0.02 as total_rounding_error to dispatch
            # in lines as 2 x 0.01.
            repartition_line_amounts = [
                round(tax_amount * line.factor, precision_rounding=prec)
                for line in tax_repartition_lines
            ]
            total_rounding_error = round(factorized_tax_amount -
                                         sum(repartition_line_amounts),
                                         precision_rounding=prec)
            nber_rounding_steps = int(
                abs(total_rounding_error / currency.rounding))
            rounding_error = round(
                nber_rounding_steps
                and total_rounding_error / nber_rounding_steps or 0.0,
                precision_rounding=prec)

            for repartition_line, line_amount in zip(tax_repartition_lines,
                                                     repartition_line_amounts):

                if nber_rounding_steps:
                    line_amount += rounding_error
                    nber_rounding_steps -= 1

                if not include_caba_tags and tax.tax_exigibility == 'on_payment':
                    repartition_line_tags = self.env['account.account.tag']
                else:
                    repartition_line_tags = repartition_line.tag_ids

                taxes_vals.append({
                    'id':
                    tax.id,
                    'name':
                    partner and tax.with_context(lang=partner.lang).name
                    or tax.name,
                    'amount':
                    sign * line_amount,
                    'base':
                    round(sign * tax_base_amount, precision_rounding=prec),
                    'sequence':
                    tax.sequence,
                    'account_id':
                    tax.cash_basis_transition_account_id.id
                    if tax.tax_exigibility == 'on_payment' else
                    repartition_line.account_id.id,
                    'analytic':
                    tax.analytic,
                    'price_include':
                    price_include,
                    'tax_exigibility':
                    tax.tax_exigibility,
                    'tax_repartition_line_id':
                    repartition_line.id,
                    'group':
                    groups_map.get(tax),
                    'tag_ids': (repartition_line_tags + subsequent_tags).ids +
                    product_tag_ids,
                    'tax_ids':
                    subsequent_taxes.ids,
                })

                if not repartition_line.account_id:
                    total_void += line_amount

            # Affect subsequent taxes
            if tax.include_base_amount:
                base += factorized_tax_amount
                if not price_include:
                    skip_checkpoint = True

            total_included += factorized_tax_amount
            i += 1

        base_taxes_for_tags = taxes
        if not include_caba_tags:
            base_taxes_for_tags = base_taxes_for_tags.filtered(
                lambda x: x.tax_exigibility != 'on_payment')

        base_rep_lines = base_taxes_for_tags.mapped(
            is_refund and 'refund_repartition_line_ids'
            or 'invoice_repartition_line_ids').filtered(
                lambda x: x.repartition_type == 'base')

        return {
            'base_tags': base_rep_lines.tag_ids.ids + product_tag_ids,
            'taxes': taxes_vals,
            'total_excluded': sign * total_excluded,
            'total_included': sign * currency.round(total_included),
            'total_void': sign * currency.round(total_void),
        }
Exemple #32
0
    def print_date_wise_stock_register(self):
        Move = self.env['stock.move']
        Product = self.env['product.product']
        start_time = fields.datetime.now()
        from_date = self.from_date
        to_date = self.to_date
        if not (self.product_ids or self.categ_ids):
            products = Product.search([('type', '=', 'product')])
        elif self.report_by == 'by_products':
            products = self.product_ids
        else:
            products = Product.search([('categ_id', 'in', self.categ_ids.ids)])

        # Date wise opening quantity
        product_quantities = products._compute_quantities_dict(
            False, False, False, from_date, to_date)

        # Received data
        in_moves = Move.read_group(
            [('date', '>=', from_date), ('date', '<', to_date),
             ('product_id', 'in', products.ids), ('state', '=', 'done'),
             ('picking_code', '=', 'incoming'),
             ('location_dest_id.usage', '=', 'internal')],
            ['product_uom_qty', 'price_unit'], ['product_id'])
        in_move_dict = dict((item['product_id'][0], (item['product_uom_qty'],
                                                     item['price_unit']))
                            for item in in_moves)

        # Issued data
        out_moves = Move.read_group([('date', '>=', from_date),
                                     ('date', '<', to_date),
                                     ('product_id', 'in', products.ids),
                                     ('state', '=', 'done'),
                                     ('picking_code', '=', 'outgoing')],
                                    ['product_uom_qty', 'price_unit'],
                                    ['product_id'])
        out_move_dict = dict((item['product_id'][0], (item['product_uom_qty'],
                                                      item['price_unit']))
                             for item in out_moves)
        report_data = []

        for categ in products.categ_id:
            report_data.append([categ.display_name])
            categ_products = products.filtered(lambda x: x.categ_id == categ)
            for product in categ_products:
                received_qty = received_price_unit = issued_qty = issued_value = 0
                product_id = product.id

                # Prepare Opening Data
                opening_qty = product_quantities[product_id]['qty_available']
                opening_value = round(opening_qty * product.standard_price,
                                      precision_rounding=4)

                # Prepare Received data
                if in_move_dict.get(product_id):
                    received_qty = in_move_dict[product_id][0]
                    received_price_unit = in_move_dict[product_id][1]
                received_value = round(received_qty * received_price_unit,
                                       precision_rounding=4)

                # prepare Issued Data
                if out_move_dict.get(product_id):
                    issued_qty = out_move_dict[product_id][0]
                    issued_value = (issued_qty * out_move_dict[product_id][1])

                # Prepare Closing Quantity
                closing_qty = opening_qty + received_qty - issued_qty
                closing_value = opening_value + received_value - issued_value

                product_data = [
                    product.name,
                    opening_qty,
                    opening_value,
                    received_qty,
                    received_value,
                    issued_qty,
                    issued_value,
                    closing_qty,
                    closing_value,
                ]
                report_data.append(product_data)

        output = io.BytesIO()
        workbook = xlsxwriter.Workbook(output, {'in_memory': True})
        worksheet = workbook.add_worksheet()

        report_title_style = workbook.add_format({
            'align': 'center',
            'bold': True,
            'font_size': 16,
            'bg_color': '#C8EAAB'
        })
        worksheet.merge_range('C2:F2', 'Datewise Stock Register',
                              report_title_style)

        report_small_title_style = workbook.add_format({
            'bold': True,
            'font_size': 14
        })
        worksheet.write(3, 3, ('From %s to %s' % (format_date(
            self.env, from_date), format_date(self.env, to_date))),
                        report_small_title_style)

        column_product_style = workbook.add_format({
            'bold': True,
            'bg_color': '#EEED8A',
            'font_size': 12
        })
        column_received_style = workbook.add_format({
            'bold': True,
            'bg_color': '#A2D374',
            'font_size': 12
        })
        column_issued_style = workbook.add_format({
            'bold': True,
            'bg_color': '#F8715F',
            'font_size': 12
        })
        row_categ_style = workbook.add_format({
            'bold': True,
            'bg_color': '#6B8DE3'
        })

        # set the width od the column
        worksheet.set_column(0, 8, 20)

        worksheet.write(6, 0, 'Product', column_product_style)
        worksheet.write(6, 1, 'Opening Quantity', column_product_style)
        worksheet.write(6, 2, 'Opening Value', column_product_style)
        worksheet.write(6, 3, 'Received Quantity', column_received_style)
        worksheet.write(6, 4, 'Received Value', column_received_style)
        worksheet.write(6, 5, 'Issued Quantity', column_issued_style)
        worksheet.write(6, 6, 'Issued Value', column_issued_style)
        worksheet.write(6, 7, 'Closing Quantity', column_product_style)
        worksheet.write(6, 8, 'Closing Value', column_product_style)
        col = 0
        row = 7

        for line in report_data:
            col = 0
            if len(line) == 1:
                # worksheet.write(row, col, line[0], row_categ_style)
                worksheet.merge_range('A%s:I%s' % (row + 1, row + 1), line[0],
                                      row_categ_style)

            else:
                for l in line:
                    worksheet.write(row, col, l)
                    col += 1
            row += 1
        workbook.close()
        xlsx_data = output.getvalue()

        self.file_data = base64.encodebytes(xlsx_data)
        end_time = fields.datetime.now()
        _logger.info("\n\nTOTAL PRINTING TIME IS : %s \n" %
                     (end_time - start_time))
        return {
            'type':
            'ir.actions.act_url',
            'url':
            '/web/content/?model={}&id={}&field=file_data&filename={}&download=true'
            .format(self._name, self.id, 'StockRegisterReport'),
            'target':
            'self',
        }
Exemple #33
0
 def _inverse_requested_hours(self):
     for day in self:
         amount = (float_utils.round(ROUNDING_FACTOR * day.requested_hours /
                                     day.available_hours) /
                   ROUNDING_FACTOR) if day.available_hours else 0.0
         day.request_amount = max(min(amount, 1.0), 0.0)
    def get_parents_childs(self, date_from, date_to, parent_id, data_from):
        """
        Desc : Get budget accounts(childs) related to parent account,with budget data

        :param date_from:
        :param date_to:
        :param parent_id:
        :return:
        """

        #print(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>DATA ", date_from, date_to, parent_id,data_from['days_days'],data_from['start_year_date'], data_from['end_year_date'] )

        # get childs related to parent account with budget data

        sql_query = """

select
                 account.id ,
                 account.code ,
                 account.name ,
                 sum(amount)  practical ,

                 round((( select  sum(planned_amount) from
                crossovered_budget_lines crossbsubs
                 join account_budget_post postsubs on (crossbsubs.general_budget_id = postsubs.id)
                 join account_account accountsubs on (postsubs.account_id = accountsubs.id)
                 join account_account account_parensubst on (accountsubs.parent_id = account_parensubst.id)
                 join account_analytic_account analyticsubs on (crossbsubs.analytic_account_id = analyticsubs.id)
                 

                where accountsubs.id = account.id and analyticsubs.analytic_type = '""" + data_from[
            'analytic_type'] + """' and date_from between '""" + data_from[
                'start_year_date'] + """-01-01' and '""" + data_from[
                    'end_year_date'] + """-12-31'
) / 365) * """ + str(data_from['days_days'] + 1) + """,2)  planned_amount  ,
sum(amount) -
round(
(( select  sum(planned_amount) from
                crossovered_budget_lines crossbsubs
                 join account_budget_post postsubs on (crossbsubs.general_budget_id = postsubs.id)
                 join account_account accountsubs on (postsubs.account_id = accountsubs.id)
                 join account_account account_parensubst on (accountsubs.parent_id = account_parensubst.id)
                 join account_analytic_account analyticsubs on (crossbsubs.analytic_account_id = analyticsubs.id)
                 

                where accountsubs.id = account.id and analyticsubs.analytic_type = '""" + data_from[
                        'analytic_type'] + """' and date_from between '""" + data_from[
                            'start_year_date'] + """-01-01' and '""" + data_from[
                                'end_year_date'] + """-12-31'
) / 365 * """ + str(data_from['days_days'] +
                    1) + """),2) deviation ,


round((sum(amount) /

((( select  sum(planned_amount) from
                crossovered_budget_lines crossbsubs
                 join account_budget_post postsubs on (crossbsubs.general_budget_id = postsubs.id)
                 join account_account accountsubs on (postsubs.account_id = accountsubs.id)
                 join account_account account_parensubst on (accountsubs.parent_id = account_parensubst.id)
                 join account_analytic_account analyticsubs on (crossbsubs.analytic_account_id = analyticsubs.id)
                 

                where accountsubs.id = account.id and analyticsubs.analytic_type = '""" + data_from[
                        'analytic_type'] + """' and date_from between '""" + data_from[
                            'start_year_date'] + """-01-01' and '""" + data_from[
                                'end_year_date'] + """-12-31'
) / 365) * """ + str(data_from['days_days'] +
                     1) + """))*100,2) percentage



from account_analytic_line line
 join account_analytic_account analytic on line.account_id = analytic.id
 join account_account account on line.general_account_id = account.id
 join account_account account_parent on (account.parent_id = account_parent.id)

 where account.parent_id = """ + str(
                         parent_id
                     ) + """ and analytic.analytic_type = '""" + data_from[
                         'analytic_type'] + """' and
 date between '""" + date_from + """' and '""" + date_to + """'  group by account.id

                    """

        #print(">>>>>>>>>>>>>>>>>>>>>>>>>>>>",sql_query)

        # Exceute query
        self._cr.execute(sql_query)

        # return result
        return self._cr.dictfetchall()