84 lines
4.2 KiB
Python
84 lines
4.2 KiB
Python
# -*- coding: utf-8 -*-
|
|
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
|
|
|
import datetime
|
|
import dateutil.parser as dparser
|
|
from re import findall as re_findall
|
|
|
|
from odoo import fields, models
|
|
from odoo.tools import get_lang
|
|
|
|
|
|
class StockMove(models.Model):
|
|
_inherit = "stock.move"
|
|
|
|
use_expiration_date = fields.Boolean(
|
|
string='Use Expiration Date', related='product_id.use_expiration_date')
|
|
|
|
def _generate_serial_move_line_commands(self, field_data, location_dest_id=False, origin_move_line=None):
|
|
"""Override to add a default `expiration_date` into the move lines values."""
|
|
move_lines_commands = super()._generate_serial_move_line_commands(field_data, location_dest_id, origin_move_line)
|
|
if self.product_id.use_expiration_date:
|
|
date = fields.Datetime.today() + datetime.timedelta(days=self.product_id.expiration_time)
|
|
for move_line_command in move_lines_commands:
|
|
move_line_vals = move_line_command[2]
|
|
if 'expiration_date' not in move_line_vals:
|
|
move_line_vals['expiration_date'] = date
|
|
return move_lines_commands
|
|
|
|
def _convert_string_into_field_data(self, string, options):
|
|
res = super()._convert_string_into_field_data(string, options)
|
|
if not res:
|
|
try:
|
|
datetime = dparser.parse(string, **options)
|
|
if self and not self.use_expiration_date:
|
|
# The datetime was correctly parsed but this move's product doesn't use expiration date.
|
|
return "ignore"
|
|
return {'expiration_date': datetime}
|
|
except ValueError:
|
|
pass
|
|
return res
|
|
|
|
def _get_formating_options(self, strings):
|
|
options = super()._get_formating_options(strings)
|
|
separators = "-/ "
|
|
date_regex = f'[^{separators}]+'
|
|
for string in strings:
|
|
# Searches for a date.
|
|
date_data = re_findall(date_regex, string)
|
|
if len(date_data) < 2: # Not enough data.
|
|
continue
|
|
value_1, value_2 = date_data[:2]
|
|
if re_findall('[a-zA-Z]', value_1):
|
|
# Assumes the first value is the mounth (written in letters). Don't add any option
|
|
# as mounth as the first date's value is the default behavior for `dateutil.parse`.
|
|
break
|
|
# Try to guess if the first data is the day or the year.
|
|
if int(value_1) > 31:
|
|
options['yearfirst'] = True
|
|
break
|
|
elif int(value_1) > 12 and (re_findall('[a-zA-Z]', value_2) or int(value_2) <= 12):
|
|
options['dayfirst'] = True
|
|
break
|
|
else: # Too ambiguous, gets the option from the user's lang's date setting.
|
|
user_lang_format = get_lang(self.env).date_format
|
|
if re_findall('^%[mbB]', user_lang_format): # First parameter is for month.
|
|
return options
|
|
elif re_findall('^%[djaA]', user_lang_format): # First parameter is for day.
|
|
options['dayfirst'] = True
|
|
break
|
|
elif re_findall('^%[yY]', user_lang_format): # First parameter is for year.
|
|
options['yearfirst'] = True
|
|
break
|
|
return options
|
|
|
|
def _update_reserved_quantity(self, need, location_id, lot_id=None, package_id=None, owner_id=None, strict=True):
|
|
if self.product_id.use_expiration_date:
|
|
return super(StockMove, self.with_context(with_expiration=self.date))._update_reserved_quantity(need, location_id, lot_id, package_id, owner_id, strict)
|
|
return super()._update_reserved_quantity(need, location_id, lot_id, package_id, owner_id, strict)
|
|
|
|
def _get_available_quantity(self, location_id, lot_id=None, package_id=None, owner_id=None, strict=False, allow_negative=False):
|
|
if self.product_id.use_expiration_date:
|
|
return super(StockMove, self.with_context(with_expiration=self.date))._get_available_quantity(location_id, lot_id, package_id, owner_id, strict, allow_negative)
|
|
return super()._get_available_quantity(location_id, lot_id, package_id, owner_id, strict, allow_negative)
|