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)
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, }
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)
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
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
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, }
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']
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
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)
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()), }
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)
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)
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, }
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}
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'))
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()), }
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()), }
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()), }
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()), }
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
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()
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)
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)
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), }
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', }
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()