pos_order.py 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139
  1. # -*- coding: utf-8 -*-
  2. # Part of Odoo. See LICENSE file for full copyright and licensing details.
  3. from odoo import api, fields, models, _
  4. from odoo.tools import float_compare, float_is_zero
  5. class PosOrder(models.Model):
  6. _inherit = 'pos.order'
  7. currency_rate = fields.Float(compute='_compute_currency_rate', store=True, digits=0, readonly=True)
  8. crm_team_id = fields.Many2one('crm.team', string="Sales Team", ondelete="set null")
  9. sale_order_count = fields.Integer(string='Sale Order Count', compute='_count_sale_order', readonly=True, groups="sales_team.group_sale_salesman")
  10. def _count_sale_order(self):
  11. for order in self:
  12. order.sale_order_count = len(order.lines.mapped('sale_order_origin_id'))
  13. @api.model
  14. def _complete_values_from_session(self, session, values):
  15. values = super(PosOrder, self)._complete_values_from_session(session, values)
  16. values.setdefault('crm_team_id', session.config_id.crm_team_id.id)
  17. return values
  18. @api.depends('pricelist_id.currency_id', 'date_order', 'company_id')
  19. def _compute_currency_rate(self):
  20. for order in self:
  21. date_order = order.date_order or fields.Datetime.now()
  22. order.currency_rate = self.env['res.currency']._get_conversion_rate(order.company_id.currency_id, order.pricelist_id.currency_id, order.company_id, date_order)
  23. def _prepare_invoice_vals(self):
  24. invoice_vals = super(PosOrder, self)._prepare_invoice_vals()
  25. invoice_vals['team_id'] = self.crm_team_id.id
  26. sale_orders = self.lines.mapped('sale_order_origin_id')
  27. if sale_orders:
  28. if sale_orders[0].partner_invoice_id.id != sale_orders[0].partner_shipping_id.id:
  29. invoice_vals['partner_shipping_id'] = sale_orders[0].partner_shipping_id.id
  30. else:
  31. addr = self.partner_id.address_get(['delivery'])
  32. invoice_vals['partner_shipping_id'] = addr['delivery']
  33. if sale_orders[0].payment_term_id:
  34. invoice_vals['invoice_payment_term_id'] = sale_orders[0].payment_term_id.id
  35. if sale_orders[0].partner_invoice_id != sale_orders[0].partner_id:
  36. invoice_vals['partner_id'] = sale_orders[0].partner_invoice_id.id
  37. return invoice_vals
  38. @api.model
  39. def create_from_ui(self, orders, draft=False):
  40. order_ids = super(PosOrder, self).create_from_ui(orders, draft)
  41. for order in self.sudo().browse([o['id'] for o in order_ids]):
  42. for line in order.lines.filtered(lambda l: l.product_id == order.config_id.down_payment_product_id and l.qty != 0 and (l.sale_order_origin_id or l.refunded_orderline_id.sale_order_origin_id)):
  43. sale_lines = line.sale_order_origin_id.order_line or line.refunded_orderline_id.sale_order_origin_id.order_line
  44. sale_order_origin = line.sale_order_origin_id or line.refunded_orderline_id.sale_order_origin_id
  45. sale_line = self.env['sale.order.line'].create({
  46. 'order_id': sale_order_origin.id,
  47. 'product_id': line.product_id.id,
  48. 'price_unit': line.price_unit,
  49. 'product_uom_qty': 0,
  50. 'tax_id': [(6, 0, line.tax_ids.ids)],
  51. 'is_downpayment': True,
  52. 'discount': line.discount,
  53. 'sequence': sale_lines and sale_lines[-1].sequence + 1 or 10,
  54. })
  55. line.sale_order_line_id = sale_line
  56. so_lines = order.lines.mapped('sale_order_line_id')
  57. # confirm the unconfirmed sale orders that are linked to the sale order lines
  58. sale_orders = so_lines.mapped('order_id')
  59. for sale_order in sale_orders.filtered(lambda so: so.state in ['draft', 'sent']):
  60. sale_order.action_confirm()
  61. # update the demand qty in the stock moves related to the sale order line
  62. # flush the qty_delivered to make sure the updated qty_delivered is used when
  63. # updating the demand value
  64. so_lines.flush_recordset(['qty_delivered'])
  65. # track the waiting pickings
  66. waiting_picking_ids = set()
  67. for so_line in so_lines:
  68. so_line_stock_move_ids = so_line.move_ids.group_id.stock_move_ids
  69. for stock_move in so_line.move_ids:
  70. picking = stock_move.picking_id
  71. if not picking.state in ['waiting', 'confirmed', 'assigned']:
  72. continue
  73. new_qty = so_line.product_uom_qty - so_line.qty_delivered
  74. if float_compare(new_qty, 0, precision_rounding=stock_move.product_uom.rounding) <= 0:
  75. new_qty = 0
  76. stock_move.product_uom_qty = so_line.compute_uom_qty(new_qty, stock_move, False)
  77. #If the product is delivered with more than one step, we need to update the quantity of the other steps
  78. for move in so_line_stock_move_ids.filtered(lambda m: m.state in ['waiting', 'confirmed'] and m.product_id == stock_move.product_id):
  79. move.product_uom_qty = stock_move.product_uom_qty
  80. waiting_picking_ids.add(move.picking_id.id)
  81. waiting_picking_ids.add(picking.id)
  82. def is_product_uom_qty_zero(move):
  83. return float_is_zero(move.product_uom_qty, precision_rounding=move.product_uom.rounding)
  84. # cancel the waiting pickings if each product_uom_qty of move is zero
  85. for picking in self.env['stock.picking'].browse(waiting_picking_ids):
  86. if all(is_product_uom_qty_zero(move) for move in picking.move_ids):
  87. picking.action_cancel()
  88. return order_ids
  89. def action_view_sale_order(self):
  90. self.ensure_one()
  91. linked_orders = self.lines.mapped('sale_order_origin_id')
  92. return {
  93. 'type': 'ir.actions.act_window',
  94. 'name': _('Linked Sale Orders'),
  95. 'res_model': 'sale.order',
  96. 'view_mode': 'tree,form',
  97. 'domain': [('id', 'in', linked_orders.ids)],
  98. }
  99. class PosOrderLine(models.Model):
  100. _inherit = 'pos.order.line'
  101. sale_order_origin_id = fields.Many2one('sale.order', string="Linked Sale Order")
  102. sale_order_line_id = fields.Many2one('sale.order.line', string="Source Sale Order Line")
  103. down_payment_details = fields.Text(string="Down Payment Details")
  104. def _export_for_ui(self, orderline):
  105. result = super()._export_for_ui(orderline)
  106. # NOTE We are not exporting 'sale_order_line_id' because it is being used in any views in the POS App.
  107. result['down_payment_details'] = bool(orderline.down_payment_details) and orderline.down_payment_details
  108. result['sale_order_origin_id'] = bool(orderline.sale_order_origin_id) and orderline.sale_order_origin_id.read(fields=['name'])[0]
  109. return result
  110. def _order_line_fields(self, line, session_id):
  111. result = super()._order_line_fields(line, session_id)
  112. vals = result[2]
  113. if vals.get('sale_order_origin_id', False):
  114. vals['sale_order_origin_id'] = vals['sale_order_origin_id']['id']
  115. if vals.get('sale_order_line_id', False):
  116. vals['sale_order_line_id'] = vals['sale_order_line_id']['id']
  117. return result