# -*- coding: utf-8 -*- # Part of Odoo. See LICENSE file for full copyright and licensing details. from odoo import api, fields, models, _ class SaleOrder(models.Model): _inherit = 'sale.order' pos_order_line_ids = fields.One2many('pos.order.line', 'sale_order_origin_id', string="Order lines Transfered to Point of Sale", readonly=True, groups="point_of_sale.group_pos_user") pos_order_count = fields.Integer(string='Pos Order Count', compute='_count_pos_order', readonly=True, groups="point_of_sale.group_pos_user") amount_unpaid = fields.Monetary(string='Unpaid Amount', compute='_compute_amount_unpaid', store=True, help="The amount due from the sale order.") def _count_pos_order(self): for order in self: linked_orders = order.pos_order_line_ids.mapped('order_id') order.pos_order_count = len(linked_orders) def action_view_pos_order(self): self.ensure_one() linked_orders = self.pos_order_line_ids.mapped('order_id') return { 'type': 'ir.actions.act_window', 'name': _('Linked POS Orders'), 'res_model': 'pos.order', 'view_mode': 'tree,form', 'domain': [('id', 'in', linked_orders.ids)], } @api.depends('order_line', 'amount_total', 'order_line.invoice_lines.parent_state', 'order_line.invoice_lines.price_total', 'order_line.pos_order_line_ids') def _compute_amount_unpaid(self): for sale_order in self: total_invoice_paid = sum(sale_order.order_line.filtered(lambda l: not l.display_type).mapped('invoice_lines').filtered(lambda l: l.parent_state != 'cancel').mapped('price_total')) total_pos_paid = sum(sale_order.order_line.filtered(lambda l: not l.display_type).mapped('pos_order_line_ids.price_subtotal_incl')) sale_order.amount_unpaid = sale_order.amount_total - (total_invoice_paid + total_pos_paid) class SaleOrderLine(models.Model): _inherit = 'sale.order.line' pos_order_line_ids = fields.One2many('pos.order.line', 'sale_order_line_id', string="Order lines Transfered to Point of Sale", readonly=True, groups="point_of_sale.group_pos_user") @api.depends('pos_order_line_ids.qty', 'pos_order_line_ids.order_id.picking_ids', 'pos_order_line_ids.order_id.picking_ids.state') def _compute_qty_delivered(self): super()._compute_qty_delivered() for sale_line in self: if all(picking.state == 'done' for picking in sale_line.pos_order_line_ids.order_id.picking_ids): sale_line.qty_delivered += sum((self._convert_qty(sale_line, pos_line.qty, 'p2s') for pos_line in sale_line.pos_order_line_ids if sale_line.product_id.type != 'service'), 0) @api.depends('pos_order_line_ids.qty') def _compute_qty_invoiced(self): super()._compute_qty_invoiced() for sale_line in self: sale_line.qty_invoiced += sum([self._convert_qty(sale_line, pos_line.qty, 'p2s') for pos_line in sale_line.pos_order_line_ids], 0) def _get_sale_order_fields(self): return ["product_id", "display_name", "price_unit", "product_uom_qty", "tax_id", "qty_delivered", "qty_invoiced", "discount", "qty_to_invoice", "price_total"] def read_converted(self): field_names = self._get_sale_order_fields() results = [] for sale_line in self: if sale_line.product_type: product_uom = sale_line.product_id.uom_id sale_line_uom = sale_line.product_uom item = sale_line.read(field_names)[0] if sale_line.product_id.tracking != 'none': item['lot_names'] = sale_line.move_ids.move_line_ids.lot_id.mapped('name') if product_uom == sale_line_uom: results.append(item) continue item['product_uom_qty'] = self._convert_qty(sale_line, item['product_uom_qty'], 's2p') item['qty_delivered'] = self._convert_qty(sale_line, item['qty_delivered'], 's2p') item['qty_invoiced'] = self._convert_qty(sale_line, item['qty_invoiced'], 's2p') item['qty_to_invoice'] = self._convert_qty(sale_line, item['qty_to_invoice'], 's2p') item['price_unit'] = sale_line_uom._compute_price(item['price_unit'], product_uom) results.append(item) elif sale_line.display_type == 'line_note': if results: if results[-1].get('customer_note'): results[-1]['customer_note'] += "--" + sale_line.name else: results[-1]['customer_note'] = sale_line.name return results @api.model def _convert_qty(self, sale_line, qty, direction): """Converts the given QTY based on the given SALE_LINE and DIR. if DIR='s2p': convert from sale line uom to product uom if DIR='p2s': convert from product uom to sale line uom """ product_uom = sale_line.product_id.uom_id sale_line_uom = sale_line.product_uom if direction == 's2p': return sale_line_uom._compute_quantity(qty, product_uom, False) elif direction == 'p2s': return product_uom._compute_quantity(qty, sale_line_uom, False) def unlink(self): # do not delete downpayment lines created from pos pos_downpayment_lines = self.filtered(lambda line: line.is_downpayment and line.sudo().pos_order_line_ids) return super(SaleOrderLine, self - pos_downpayment_lines).unlink() @api.depends('pos_order_line_ids') def _compute_untaxed_amount_invoiced(self): super()._compute_untaxed_amount_invoiced() for line in self: line.untaxed_amount_invoiced += sum(line.pos_order_line_ids.mapped('price_subtotal')) def _get_downpayment_line_price_unit(self, invoices): return super()._get_downpayment_line_price_unit(invoices) + sum( pol.price_unit for pol in self.pos_order_line_ids )