Files
enterprise-addons/pos_settle_due/models/res_partner.py
T

131 lines
6.2 KiB
Python

# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from odoo import fields, models, api
class ResPartner(models.Model):
_inherit = 'res.partner'
pos_orders_amount_due = fields.Float(string="Sum of customers PoS orders's due amount", compute="_compute_pos_orders_amount_due")
invoices_amount_due = fields.Float(string="Sum of customers's invoice due amount", compute="_compute_invoices_amount_due")
def _compute_pos_orders_amount_due(self):
commercial_partner_ids = {p.id: p.commercial_partner_id.id for p in self}
# Fetch the total sum of 'customer_due_total' grouped by 'commercial_partner_id'
pos_orders = self.env['pos.order']._read_group(
domain=[
('commercial_partner_id', 'in', set(commercial_partner_ids.values())),
('state', 'in', ['paid', 'done'])
],
groupby=['commercial_partner_id'],
aggregates=['customer_due_total:sum']
)
due_map = {order[0].id: order[1] for order in pos_orders}
for partner in self:
partner.pos_orders_amount_due = due_map.get(commercial_partner_ids[partner.id], 0.0)
def _compute_invoices_amount_due(self):
commercial_partner_ids = {p.id: p.commercial_partner_id.id for p in self}
# Fetch the sum of 'pos_amount_unsettled' of unpaid invoices grouped by 'commercial_partner_id'
invoices = self.env['account.move']._read_group(
domain=[('commercial_partner_id', 'in', set(commercial_partner_ids.values())),
('state', '=', 'posted'),
('payment_state', 'in', ('not_paid', 'partial')),
('move_type', 'in', self.env['account.move'].get_sale_types())],
groupby=['commercial_partner_id'],
aggregates=['pos_amount_unsettled:sum']
)
due_map = {inv[0].id: inv[1] for inv in invoices}
for partner in self:
partner.invoices_amount_due = due_map.get(commercial_partner_ids[partner.id], 0.0)
def get_total_due(self, config_id):
config = self.env['pos.config'].browse(config_id)
pos_currency = config.currency_id
company_currency = self.env.company.currency_id
date = fields.Date.today()
pos_payments = self.env['pos.order'].search([
('commercial_partner_id', '=', self.commercial_partner_id.id), ('state', '=', 'paid'),
('session_id.state', '!=', 'closed')]).mapped('payment_ids')
# pos.payment.amount is expressed in the currency of its order, so it is
# converted to the PoS currency instead of the company one.
total_settled = sum(
payment.currency_id._convert(payment.amount, pos_currency, self.env.company, date)
for payment in pos_payments.filtered_domain([('payment_method_id.type', '=', 'pay_later')])
)
self_sudo = self
group_pos_user = self.env.ref('point_of_sale.group_pos_user')
if group_pos_user in self.env.user.all_group_ids:
self_sudo = self.sudo() # allow POS users without accounting rights to settle dues
# total_due comes from the accounting entries, it is in company currency.
total_due = self_sudo.parent_id.total_due if self.parent_id else self_sudo.total_due
if company_currency != pos_currency:
total_due = company_currency._convert(total_due, pos_currency, self.env.company, date)
total_due += total_settled
partner = self.env['res.partner']._load_pos_data_read(self, config)[0]
partner['total_due'] = total_due
return {
'res.partner': [partner],
}
def get_all_total_due(self, config_id):
due_amounts = []
partners = self.exists()
for partner in partners:
due_amounts.append(partner.get_total_due(config_id))
return due_amounts
def get_matching_paylater_orders(self):
self.ensure_one()
pay_later_refund_orders = self.env["pos.order"].search([
("commercial_partner_id", "=", self.id),
("state", "in", ["paid", "done"]),
]).filtered(
lambda o: (
o.refunded_order_id
and any(
p.payment_method_id.type == "pay_later"
for p in o.payment_ids
)
)
)
original_orders = pay_later_refund_orders.mapped("refunded_order_id").filtered(lambda o: o.state in ["paid", "done"])
orders_matched = []
for order in original_orders:
refund_orders = pay_later_refund_orders.filtered(lambda o: o.refunded_order_id.id == order.id)
original_pay_later_amount = sum(order.payment_ids.filtered(lambda p: p.payment_method_id.type == "pay_later").mapped("amount"))
refund_pay_later_amount = sum(refund_orders.mapped("payment_ids").filtered(lambda p: p.payment_method_id.type == "pay_later").mapped("amount"))
if order.currency_id.is_zero(original_pay_later_amount + refund_pay_later_amount):
orders_matched += order.ids + refund_orders.ids
return orders_matched
@api.model
def _load_pos_data_fields(self, config):
params = super()._load_pos_data_fields(config)
if self.env.user.has_group('account.group_account_readonly') or self.env.user.has_group('account.group_account_invoice'):
params += ['credit_limit', 'total_due', 'use_partner_credit_limit', 'pos_orders_amount_due', 'invoices_amount_due', 'commercial_partner_id']
return params
@api.model
def _load_pos_data_read(self, records, config):
read_records = super()._load_pos_data_read(records, config)
if config.currency_id != self.env.company.currency_id and (self.env.user.has_group('account.group_account_readonly') or self.env.user.has_group('account.group_account_invoice')):
for record in read_records:
record['total_due'] = self.env.company.currency_id._convert(record['total_due'], config.currency_id, self.env.company, fields.Date.today())
return read_records
def _compute_has_moves(self):
super()._compute_has_moves()
for partner in self.filtered(lambda p: not p.has_moves):
partner.has_moves = partner.total_due != 0