Add csv import wizard to shipment internal.

This commit refs #11606
This commit is contained in:
Sergio Morillo 2020-04-09 12:24:19 +02:00
parent d86b01104e
commit 5f780dc502
11 changed files with 187 additions and 25 deletions

View File

@ -13,6 +13,7 @@ def register():
stock.StockCsvImport,
shipment.ShipmentOutReturn,
shipment.ShipmentIn,
shipment.ShipmentInternal,
module='stock_csv_import', type_='model')
Pool.register(
stock.CsvImport,

View File

@ -13,6 +13,8 @@ class Configuration(metaclass=PoolMeta):
'Shipment out Return CSV Headers')
shipment_in_csv_headers = fields.Char(
'Shipment in CSV Headers')
shipment_internal_csv_headers = fields.Char(
'Shipment interal CSV Headers')
@classmethod
def __register__(cls, module_name):

View File

@ -78,6 +78,10 @@ msgctxt "selection:stock.shipment.csv_import.start,shipment_type:"
msgid "Out return"
msgstr "Devolución cliente"
msgctxt "selection:stock.shipment.csv_import.start,shipment_type:"
msgid "Internal"
msgstr "Interno"
msgctxt "model:ir.action,name:wizard_shipment_out_return_csv_import"
msgid "Import CSV Shipment Out return"
msgstr "Importar CSV albarán devolución de cliente"
@ -94,6 +98,14 @@ msgctxt "model:ir.ui.menu,name:menu_wizard_shipment_in_csv_import"
msgid "Import CSV Shipment In"
msgstr "Importar CSV proveedor"
msgctxt "model:ir.action,name:wizard_shipment_internal_csv_import"
msgid "Import CSV Shipment Internal"
msgstr "Importar CSV albarán interno"
msgctxt "model:ir.ui.menu,name:menu_wizard_shipment_internal_csv_import"
msgid "Import CSV Shipment Internal"
msgstr "Importar CSV interno"
msgctxt "model:ir.ui.menu,name:menu_stock_csv_import"
msgid "CSV Import"
msgstr "Importaciones CSV"
@ -116,4 +128,8 @@ msgstr "Albarán proveedor"
msgctxt "view:stock.configuration:"
msgid "Shipment out return"
msgstr "Albarán devolución cliente"
msgstr "Albarán devolución cliente"
msgctxt "view:stock.configuration:"
msgid "Shipment internal"
msgstr "Albarán interno"

View File

@ -5,7 +5,7 @@ from .stock import (ShipmentCSVMixin, ShipmentCSVProductMixin,
ShipmentCSVLocationMixin)
__all__ = ['ShipmentOutReturn', 'ShipmentIn', 'ShipmentInProduct',
'ShipmentOutReturnProduct']
'ShipmentOutReturnProduct', 'ShipmentInternal']
class ShipmentOutReturn(ShipmentCSVMixin, metaclass=PoolMeta):
@ -90,3 +90,20 @@ class ShipmentInLocation(ShipmentCSVLocationMixin, metaclass=PoolMeta):
'address': data['contact_address'].id
if data['contact_address'] else None
}
class ShipmentInternal(ShipmentCSVMixin, metaclass=PoolMeta):
__name__ = 'stock.shipment.internal'
@classmethod
def __setup__(cls):
super().__setup__()
cls._csv_move_field = 'incoming_moves'
@classmethod
def _get_csv_key(cls):
return ('to_location', 'from_location', ) + super()._get_csv_key()
def _set_csv_move_locations(self, move):
move.from_location = self.from_location
move.to_location = self.to_location

View File

@ -20,5 +20,14 @@
<menuitem id="menu_wizard_shipment_in_csv_import"
sequence="40" parent="stock.menu_shipment_in_form"
action="wizard_shipment_in_csv_import"/>
<!-- Wizard Shipment Internal CSV Import -->
<record model="ir.action.wizard" id="wizard_shipment_internal_csv_import">
<field name="name">Import CSV Shipment Internal</field>
<field name="wiz_name">stock.shipment.csv_import</field>
</record>
<menuitem id="menu_wizard_shipment_internal_csv_import"
sequence="40" parent="stock.menu_shipment_internal_form"
action="wizard_shipment_internal_csv_import"/>
</data>
</tryton>

View File

@ -59,27 +59,30 @@ class ShipmentCSVMixin(object):
fieldname = splitted_field[0]
else:
fieldname = field_name
if isinstance(Model._fields[fieldname], fields.Many2One):
field = Model._fields[fieldname]
relation = field.get_target().__name__
RelModel = pool.get(relation)
domain = cls._get_csv_field_extra_domain(field.name, data, row=row)
if splitted_field:
domain.append((".".join(splitted_field[1:]), '=', field_value))
else:
domain.append(('rec_name', '=', field_value))
value = RelModel.search(domain)
if user_error and field_value and not value:
cls.raise_user_error('csv_relation_not_found', (
Model.fields_get(fields_names=[fieldname]
)[fieldname]['string'],
field_value))
return value[0] if value else None
elif isinstance(Model._fields[fieldname], fields.Date):
try:
return datetime.strptime(field_value, "%Y-%m-%d").date()
except ValueError:
cls.raise_user_error('csv_date_format_error')
if getattr(Model, fieldname, False):
if isinstance(Model._fields[fieldname], fields.Many2One):
field = Model._fields[fieldname]
relation = field.get_target().__name__
RelModel = pool.get(relation)
domain = cls._get_csv_field_extra_domain(field.name, data,
row=row)
if splitted_field:
domain.append((".".join(splitted_field[1:]), '=',
field_value))
else:
domain.append(('rec_name', '=', field_value))
value = RelModel.search(domain)
if user_error and field_value and not value:
cls.raise_user_error('csv_relation_not_found', (
Model.fields_get(fields_names=[fieldname]
)[fieldname]['string'],
field_value))
return value[0] if value else None
elif isinstance(Model._fields[fieldname], fields.Date):
try:
return datetime.strptime(field_value, "%Y-%m-%d").date()
except ValueError:
cls.raise_user_error('csv_date_format_error')
return field_value
@classmethod
@ -369,7 +372,10 @@ class CsvImport(Wizard):
'wizard_shipment_out_return_csv_import'):
'stock.shipment.out.return',
Modeldata.get_id('stock_csv_import',
'wizard_shipment_in_csv_import'): 'stock.shipment.in'
'wizard_shipment_in_csv_import'): 'stock.shipment.in',
Modeldata.get_id('stock_csv_import',
'wizard_shipment_internal_csv_import'):
'stock.shipment.internal'
}
_type = actions.get(Transaction().context['action_id'], None)
return {
@ -414,7 +420,8 @@ class CsvImportStart(ModelView):
show_type = fields.Boolean('Show type')
shipment_type = fields.Selection([
('stock.shipment.out.return', 'Out return'),
('stock.shipment.in', 'In')
('stock.shipment.in', 'In'),
('stock.shipment.internal', 'Internal')
], 'Shipment type', required=True,
states={
'invisible': Not(Bool(Eval('show_type')))

2
tests/internal.csv Normal file
View File

@ -0,0 +1,2 @@
reference,effective_date,from_location,to_location,product,quantity
Reference 1,2020-04-07,Storage 1,Storage 2,1,50
1 reference effective_date from_location to_location product quantity
2 Reference 1 2020-04-07 Storage 1 Storage 2 1 50

2
tests/internal_error.csv Normal file
View File

@ -0,0 +1,2 @@
reference,effective_date,from_location,to_location,product,quantity
Reference 1,2020-04-07,Storage Error,Storage 2,1,50
1 reference effective_date from_location to_location product quantity
2 Reference 1 2020-04-07 Storage Error Storage 2 1 50

View File

@ -0,0 +1,99 @@
===========================================
Stock Shipment Internal Csv Import Scenario
===========================================
Imports::
>>> from proteus import Model, Wizard
>>> from trytond.tests.tools import activate_modules
>>> from trytond.modules.stock_csv_import.tests.tools import read_csv_file
>>> import os
>>> from trytond.modules.company.tests.tools import create_company, \
... get_company
>>> from decimal import Decimal
Install stock_csv_import::
>>> config = activate_modules('stock_csv_import')
Create company::
>>> _ = create_company()
>>> company = get_company()
Create Configuration::
>>> Configuration = Model.get('stock.configuration')
>>> config = Configuration()
>>> config.shipment_internal_csv_headers = "reference,effective_date,from_location.name,to_location.name,incoming_moves.product.id,incoming_moves.quantity"
>>> config.save()
Create Product::
>>> ProductUom = Model.get('product.uom')
>>> unit, = ProductUom.find([('name', '=', 'Unit')])
>>> ProductTemplate = Model.get('product.template')
>>> Product = Model.get('product.product')
>>> product = Product()
>>> template = ProductTemplate()
>>> template.name = 'Product 1'
>>> template.default_uom = unit
>>> template.type = 'goods'
>>> template.purchasable = True
>>> template.list_price = Decimal('10')
>>> template.cost_price = Decimal('5')
>>> template.cost_price_method = 'fixed'
>>> template.save()
>>> product.template = template
>>> product.save()
Create locations::
>>> Location = Model.get('stock.location')
>>> sto_loc1 = Location(name='Storage 1')
>>> sto_loc1.code = 'STO'
>>> sto_loc1.type = 'storage'
>>> sto_loc1.save()
>>> sto_loc2 = Location(name='Storage 2')
>>> sto_loc2.code = 'STO'
>>> sto_loc2.type = 'storage'
>>> sto_loc2.save()
CSV import wizard::
>>> ShipmentInternal = Model.get('stock.shipment.internal')
>>> Data = Model.get('ir.model.data')
>>> data, = Data.find([
... ('module', '=', 'stock_csv_import'),
... ('fs_id', '=', 'wizard_shipment_internal_csv_import')])
>>> csv_import = Wizard('stock.shipment.csv_import', action={'id': data.db_id})
>>> filename = os.path.join(os.path.dirname(__file__), 'internal.csv')
>>> csv_import.form.csv_file = read_csv_file(filename)
>>> csv_import.form.store_file = False
>>> csv_import.execute('import_')
>>> shipment, = ShipmentInternal.find([])
>>> shipment.effective_date
datetime.date(2020, 4, 7)
>>> shipment.from_location == sto_loc1
True
>>> shipment.to_location == sto_loc2
True
>>> move, = shipment.moves
>>> move.quantity
50.0
>>> move.product.name
'Product 1'
>>> move.from_location == shipment.from_location
True
>>> move.to_location == shipment.to_location
True
CSV import wizard when location does not exist::
>>> csv_import = Wizard('stock.shipment.csv_import', action={'id': data.db_id})
>>> filename = os.path.join(os.path.dirname(__file__), 'internal_error.csv')
>>> csv_import.form.csv_file = read_csv_file(filename)
>>> csv_import.execute('import_')
Traceback (most recent call last):
...
trytond.exceptions.UserError: Cannot find a From Location record with value "Storage Error". -

View File

@ -39,4 +39,9 @@ def suite():
tearDown=doctest_teardown, encoding='utf-8',
checker=doctest_checker,
optionflags=doctest.REPORT_ONLY_FIRST_FAILURE))
suite.addTests(doctest.DocFileSuite(
'scenario_shipment_internal_csv_import.rst',
tearDown=doctest_teardown, encoding='utf-8',
checker=doctest_checker,
optionflags=doctest.REPORT_ONLY_FIRST_FAILURE))
return suite

View File

@ -8,5 +8,7 @@ this repository contains the full copyright notices and license terms. -->
<field name="shipment_in_csv_headers" colspan="3"/>
<label name="shipment_out_return_csv_headers" string="Shipment out return"/>
<field name="shipment_out_return_csv_headers" colspan="3"/>
<label name="shipment_internal_csv_headers" string="Shipment internal"/>
<field name="shipment_internal_csv_headers" colspan="3"/>
</xpath>
</data>