====== AIRS-1432 Add "brexit" and "UX dimension" validation for M2M and upload ======
[[https://tasks.supplyon.de/browse/AIRS-1432|AIRS-1432 Add "brexit" and "UX dimension" validation for M2M and upload]] -> Jira
[[https://doc.supplyon.de/pages/viewpage.action?pageId=56141579|Spec im Confluence]]
===== Spezifikation =====
==== Kurzbeschreibung mit eigenen Worten ====
Abhängig vom Flag (CustomsRequired bzw. UXDimensionRequired) in der DA zugrundeliegenden Nachricht (PO oder VMI) müssen bestimmte Felder beim Import / Upload geprüft werden. Wenn das Flag auf true steht, müssen die Felder gefüllt sein.
* CustomsRequired
* Customs Value (ElementaryUnits.ElementaryUnit.CustomsValue -> TAG_UE_CUSTOMS_VALUE, CSV name)
* Customs Value UOM (-> Currency of Customs value) (ElementaryUnits.ElementaryUnit.Currency -> TAG_UE_CURRENCY, CSV name)
* Net weight (ElementaryUnits.ElementaryUnit.NetWeight -> TAG_UE_NETWEIGHT, CSV name)
* Net weight UOM (ElementaryUnits.ElementaryUnit.NetWeightUOM -> TAG_UE_NETWEIGHT_UOM, CSV name)
* Country of Origin (ElementaryUnits.ElementaryUnit.CountryOfOrigin -> TAG_UE_COUNTRY_OF_ORIGIN, CSV name)
* UXDimensionRequired
* Packaging Type (Positions.Position.UXType (?), CSV name)
* Gross Weight (Positions.Position.GrossWeight, CSV name)
* Gross Weight UoM (Positions.Position.GrossWeightUOM, CSV name)
* Length (Positions.Position.Length, CSV name)
* Length UoM (->Positions.Position.DimensionsUOM, CSV name)
* Width (Positions.Position.Width, CSV name)
* Width UoM (->Positions.Position.DimensionsUOM, CSV name)
* Height (Positions.Position., CSV name)
* Height UoM (->Positions.Position.DimensionsUOM, CSV name)
* Dimensions UoM (Positions.Position.DimensionsUOM, CSV name)
* Stackable Goods (Positions.Position.StackableGoods, CSV name)
* Hazardous Goods (Positions.Position.HazardousGoods, CSV name)
* Special Instructions (Positions.Position.SpecialInstructions, CSV name)
* Total Value (Positions.Position.TotalValue, CSV name)
* Currency (Positions.Position.Currency, CSV name)
Bei UX Dimensions müssen nicht immer alle Felder Pflichtfelder sein, sondern man muss schauen wie das Feld konfiguriert ist. Der Code kann sich wahrscheinlich an den von der UI anlehnen.
Zusätzlich muss geprüft werden:
* ob die UoM Werte vom System akzeptiert werden (sie müssen in einer "Configliste" sein -> klären wo diese Liste ist).
* ob DimensionsUOM Werte bei einer UX alle gleich sind (LengthUOM==WidthUOM && LengthUOM==HeightUOM)
Außerdem müssen die eingehenden(?) CSVs und XMLs bei PO und VMI Demand das Feld "CustomsRequired" enthalten.
CSV Upload Spec ist in dem Task [[https://tasks.supplyon.de/secure/RapidBoard.jspa?rapidView=3&projectKey=AIRS&view=detail&selectedIssue=AIRS-1474|AIRS-1474]] enthalten:\\ https://tasks.supplyon.de/secure/attachment/26880/SD_AirSupply_Interfaces_DA_V_9.3.xlsx
==== Fragen an Saskia ====
* Welche Felder genau (4 oder 5?)? -> Spec wird erweitert um die genaue Liste.
* Zitat aus Confluence zu AIRS-1433: "CSV message contains the five new fields: Customs Value, Customs Value UOM, Net weight, Net weight UOM, country of origin"
* Burkhard: Customs Value UOM -> UnitOfMeasure? -> alles beschrieben in der Spec
* UxDimensions müssen jetzt wohl auch geprüft werden?
* Ja? -> Ja
* Welche Felder? -> Spec wird erweitert um die genaue Liste.
* Welches Flag? -> UEModel.uxDimensionsRequired
* Wo in der CSV-Nachricht müssen die Felder stehen?
* Task AIRS-1433 ? -> wird von Saskia spezifiziert
===== TODO =====
* **-** DA XML Import
* **-** Import
* **+** Implement
* **-** Test
* **-** Wenn alle Felder befüllt sind, dann landen sie auch alle in der DB
* **-** Wenn CustomsRequired auf true steht, prüft die Anwendung, ob die entsprechenden Felder befüllt sind:
* **-** CustomsRequired steht auf true, und alle Felder sind befüllt (positiv)
* **-** CustomsRequired steht auf true, aber keins von diesen Feldern ist befüllt (negativ)
* **-** CustomsRequired steht auf true, aber eins von diesen Feldern ist nicht befüllt
* **-** Customs Value
* **-** Customs Value UOM
* **-** Net weight
* **-** Net weight UOM
* **-** Country of Origin
* **-** Wenn UXDimensionRequired auf true steht, prüft die Anwendung ob die entsprechenden Felder befüllt sind:
* **-** UXDimensionRequired steht auf true, und alle Felder sind befüllt (positiv)
* **-** UXDimensionRequired steht auf true, aber keins von diesen Feldern ist befüllt (negativ)
* **-** UXDimensionRequired steht auf true, aber eins von diesen Feldern ist nicht befüllt
* **-** Packaging type
* **-** Gross weight
* **-** Gross weight UOM
* **-** Length
* **-** Length UOM
* **-** Width
* **-** Width UOM
* **-** Height
* **-** Height UOM
* **-** Stackable goods
* **-** Hazardous goods
* **-** Special instructions
* **-** Total value
* **-** Currency
* **-** UoM Konsistenztests
* **-** UoM enthält validen Wert
* **-** Customs Value UOM
* **-** Net weight UOM
* **-** Gross weight UOM
* **-** Dimensions (Length, Width, Height) UOM
* **-** UoM enthält unerlaubten Wert
* **-** Customs Value UOM
* **-** Net weight UOM
* **-** Gross weight UOM
* **-** Dimensions (Length, Width, Height) UOM
* **x** Alle dimension UoMs enthalten gleichen Wert -> im Falle vom XML Import automatisch erfüllt
* **-** UoM Umrechnung
* **+** Implement
* **-** Test
* **-** DA CSV Upload
* **-** Import
* **-** Implement
* **-** ...
* **-** Implement the proper fields order
* **-** Check if all weight/dimension uoms have the same value (see ASNImportUtil.parse...())
* **-** Test
* **-** Wenn alle Felder befüllt sind, dann landen sie auch alle in der DB
* **-** Wenn CustomsRequired auf true steht, prüft die Anwendung ob die entsprechenden Felder befüllt sind:
* **-** CustomsRequired steht auf true, und alle Felder sind befüllt (positiv)
* **-** CustomsRequired steht auf true, aber keins von diesen Feldern ist befüllt (negativ)
* **-** CustomsRequired steht auf true, aber eins von diesen Feldern ist nicht befüllt
* **-** Customs Value
* **-** Customs Value UOM
* **-** Net weight
* **-** Net weight UOM
* **-** Country of Origin
* **-** Wenn UXDimensionRequired auf true steht, prüft die Anwendung ob die entsprechenden Felder befüllt sind:
* **-** UXDimensionRequired steht auf true, und alle Felder sind befüllt (positiv)
* **-** UXDimensionRequired steht auf true, aber keins von diesen Feldern ist befüllt (negativ)
* **-** UXDimensionRequired steht auf true, aber eins von diesen Feldern ist nicht befüllt
* **-** Packaging type
* **-** Gross weight
* **-** Gross weight UOM
* **-** Length
* **-** Length UOM
* **-** Width
* **-** Width UOM
* **-** Height
* **-** Height UOM
* **-** Stackable goods
* **-** Hazardous goods
* **-** Special instructions
* **-** Total value
* **-** Currency
* **-** UoM Konsistenztests
* **-** UoM enthält validen Wert
* **-** Customs Value UOM
* **-** Net weight UOM
* **-** Gross weight UOM
* **-** Dimensions (Length, Width, Height) UOM
* **-** UoM enthält unerlaubten Wert
* **-** Customs Value UOM
* **-** Net weight UOM
* **-** Gross weight UOM
* **-** Dimensions (Length, Width, Height) UOM
* **-** Alle dimension UoMs enthalten gleichen Wert
* **-** Alle dimension UoMs enthalten gleichen Wert
* **-** Eins von dimension UoMs enthält einen anderen Wert
* **-** UoM Umrechnung
* **-** Implement
* **-** Test
* **-** Flags mit SO-Order (sellside) rausschicken
* **+** Implement
* **-** Test
* **-** Flags mit VMI (sellside) rausschicken
* **+** Implement
* **-** Test
==== Original ====
* **-** DA:
* **-** M2M Boost sellside validated against the CustomsRequired and or the UXDimensionRequired flag
* **-** M2M CSV sellside validated against the CustomsRequired and or the UXDimensionRequired flag
* **-** Upload CSV files are validated against the CustomsRequired and or the UXDimensionRequired flag
* **-** PO:
* **-** CustomsRequired and UXDimensionRequired flag are sent to the CSV suppliers
* **-** CustomsRequired and UXDimensionRequired flag are sent to the Boost XML suppliers
* **-** VMI Demand:
* **-** CustomsRequired and UXDimensionRequired flag are sent to the CSV suppliers
* **-** CustomsRequired and UXDimensionRequired flag are sent to the Boost XML suppliers
**Hints:**
* Unit of Measure for Customs Value should be checked if valid according to our definition
* Unit of Measure for length, width, height has to be checked:
* against the allowed values within AirSupply
* if consistent within one message, e.g. it is not allowed to send a mix (centimeters and meter or inch and centitmeters and so on)
Attention: mandatory fields for UX dimensions (fields above marked in blue) may vary depending on the customer configuration in the TAIRFIELDCONFIG. This has to be considered for the validation
==== Misc ====
=== Tests reparieren ===
Folgende Tests wurden von meinen Änderungen betroffen und müssen nun repariert werden:
* **-** ASNValidationsTest.testGetUxMandatoryFieldUxDimensionExcluded()
* **-** ASNValidationsTest.testGetUxMandatoryFieldsWithCsvUploadUxDeminsionIncluded()
=== Default UoMs ===
== Set proper UoMs after validation ==
Nachdem die ASN importiert und validiert wurde, sollte man die richtige (interne!) UoMs setzen.
Davor muss aber geprüft werden, ob vom alten Code //wirklich// interne UoMs verwendet werden.
Hilfreich:
* Der Code in der Klasse ''ASNXMLExportHandler''
* Mein Code:
BigDecimal uxWeightInXML = XMLToolbox.getSubTagValueAsBigDecimal(uxElement, ASNXMLConstants.TAG_UX_GROSSWEIGHT, null);
WeightUtil.UOM_CONVERTER_UNITS_WEIGHT targetWeightUoM = WeightUtil.UOM_CONVERTER_UNITS_WEIGHT.getUOMConverterUnit(uxModel.getUXWeightUOM());
uxModel.setGrossWeight(DimensionsUtil.convertFromUIToModel(targetWeightUoM.name(), uxWeightInXML));
== Check if it works for "non UX Dimensions" situations ==
Im ASNXMLImportHandler:
// TODO: check if it works for "non UX Dimensions" situations!
// uxModel.setUXWeightUOM(WeightUtil.INTERNAL_GLOBAL_WEIGHT_UOM);
// uxModel.setDimensionsUom(DimensionsUtil.INTERNAL_GLOBAL_DEFAULT_LENGTH_UOM);
...
===== CSV Upload =====
Wichtige Klassen:
* ASNCSVUploadHandler
* ASNImportModelFactory
* ASNCSVLineValidationUtil
* validiert ''ASNCSVUploadModel''s **ohne** Bezug auf andere Datenstrukturen, d.h. die Validierungen, die von irgendwelchen Flags in der zugrundeliegenden Nachricht abhängig sind, laufen in der Web/ManagerEJB-Klasse ab (-> check it)
===== Änderungen, die ich machen musste =====
* Export XML -> "UX Weight UoM" auf "Gross Weight UoM" umbiegen
===== Nützliche SQL Befehle =====
-- Flags abfragen
SELECT t.CCUSTOMSDECLARATIONREQUIRED, t.CPACKDETAILSREQUIRED, t.* FROM TAIRDEMANDS t where CHEADERID=18168;
-- Flags bei der Demand, die ich verwende, setzen
UPDATE TAIRDEMANDS set CCUSTOMSDECLARATIONREQUIRED=1, CPACKDETAILSREQUIRED=1 where CHEADERID=18168;
-- Flag CENABLEUXDIMENSIONS bei dem Profile 1 setzen
update TCPPROFILES_SCD set CENABLEUXDIMENSIONS=0 where cProfileId=1;
-- Misc
SELECT t.CPROFILEID, t.* FROM TCONTROLPOINT_SCD t where cCPId=101883;
select t.CPROFILEID, t.* from TCPPROFILES_SCD t;
===== Misc =====
Die Felder, die für die Validierung von UXs notwendig sind werden in ''ASNValidations.getUxMandatoryFields()'' hinzugefügt.\\
Die Felder, die für die Validierung von UEs notwendig sind werden in ''ASNValidations.getUEMandatoryFields()'' hinzugefügt.\\
==== Gewicht UoMs ====
Die Gewichte der UXs werden momentan "nicht konsequent" berechnet. Um dies zu korrigieren am besten die Verwendungen von ''UXModel.setUXWeightUOM()'' und ''UXModel.setGrossWeightUom()'' anschauen (z.B. auch die Verwendung von ''ASNWeightModel.setWeightUoM()'').
==== Merge 20190206 ====
default_xx.properties
# Für AIRS-1472:
airsupply.asn.csv.error.uxlengthuom=$$P$$Empty or invalid UoM for UX length in line %s1, position %s2.
airsupply.asn.csv.error.uxheightuom=$$P$$Empty or invalid UoM for UX height in line %s1, position %s2.
airsupply.asn.csv.error.uxwidthuom=$$P$$Empty or invalid UoM for UX width in line %s1, position %s2.
airsupply.asn.csv.error.uxgrossweightuom=$$P$$Empty or invalid UoM for UX gross weight in line %s1, position %s2.
airsupply.asn.csv.error.uenetweightuom=$$P$$Empty or invalid UoM for UE net weight in line %s1, position %s2.
airsupply.asn.validation.business.c450.9=$$P$$C450.9 - CUST.MATNR\: %s7 /PO/VMI REF, ITEM, PO SL\: %s4 , %s5 , %s6 /UE\: %s3 /UX\: %s2 /DA ID\: %s1 - Net weight UoM is missing. As the flag for 'Customs Declaration Required' is set to TRUE in the Customer PO this value has to be declared in the associated UE.
# Für AIRS-
airsupply.asn.ue.column.netweight.withoutuom=$$P$$Net weight
airsupply.asn.ue.column.netweightuom=$$P$$Net weight UoM
airsupply.asn.uxdimensions.column.weightuom=$$P$$Weight UoM
# Für AIRS-1532 Enhance DA full download
uoms.in=$$P$$in
uoms.ft=$$P$$ft
uoms.mm=$$P$$mm
uoms.cm=$$P$$cm
uoms.m=$$P$$m
uoms.kg=$$P$$kg
uoms.lb=$$P$$lb
SQL (es hat sich herausgestellt, dass dieses Skript nicht notwendig ist, da GrossWeightUoM ein "virtuelles" Feld ist, das nur für Import und CSV Upload notwendig ist):
INSERT INTO TAIRFIELDCONFIG ( CCUSTOMERCPID, CCUSTOMERCPPROFILEID, CPROCESS, CFIELDNAME, CMANDATORY, CDISPLAYABLE, CDEFAULTDISPLAY, CSORTING, CPROCESSTRANSFER, CFORMATPATTERN, CEDITABLE )
SELECT '-1000','-1','DA-UXDimensions','GrossWeightUom','1','1','1','11','0',null,'1' FROM DUAL
WHERE NOT EXISTS ( SELECT * FROM TAIRFIELDCONFIG WHERE CCUSTOMERCPID=-1000 AND CCUSTOMERCPPROFILEID=-1 AND cProcess='DA-UXDimensions' AND cFieldName = 'GrossWeightUom');
===== PI5 Sprint 2 TODO =====
==== UoMs ====
Die UoMs berücksichtigen:
* **-** Beim Import
* **-** Beim Export
* **-** Auf der UI
==== Tickets ====
* **-** [[https://cust-projects.seeburger.de/redmine/issues/29440|rm#29440 Brexit - UOM for Length/Width/Height should be 2-digits]]
===== Misc =====
Der folgende Code wurde von mir geschrieben, wird aber nicht mehr verwendet, da jetzt immer Zentimeter und Kilogramm bei den Brexit Feldern als UoMs verwendet werden.
// the same utility method is used on the UI too
String grossWeightUom = ASNWebUtil.getWeightUoM(sasUserContext, asnModel);
WeightConverter converter = new WeightConverter.Builder()
.setSourceUom(WeightUtil.INTERNAL_GLOBAL_WEIGHT_UOM)
.setTargetUom(WeightUtil.getUnitOfMeasure(grossWeightUom)).build();
BigDecimal converted = converter.convertAndRound(uxModel.getGrossWeight());
csvModel.setGrossWeight(converted);
String translatedDimensionsUom = DimensionsUtil.getTranslatedUserDimensionUom(asnModel.getCustomerCPId(), sasUserContext);
csvModel.setLength(DimensionsUtil.convertFromModelToUi(sasUserContext, asnModel.getCustomerCPId(), uxModel.getLength()));
csvModel.setLengthUom(translatedDimensionsUom);
csvModel.setWidth(DimensionsUtil.convertFromModelToUi(sasUserContext, asnModel.getCustomerCPId(), uxModel.getWidth()));
csvModel.setWidthUom(translatedDimensionsUom);
csvModel.setHeight(DimensionsUtil.convertFromModelToUi(sasUserContext, asnModel.getCustomerCPId(), uxModel.getHeight()));
csvModel.setHeightUom(translatedDimensionsUom);