/// <summary> /// Issue an order /// </summary> public void IssueDespatchAdvice(DespatchAdviceMessageType advice) { String boundary = String.Format("------{0:N}", Guid.NewGuid()); if (this.m_configuration.UseAS2MimeEncoding) { this.Client.Post <MultipartAttachment, object>("despatchAdvice", String.Format("multipart/form-data; boundary={0}", boundary), this.CreateAttachment(advice)); } else { this.Client.Post <DespatchAdviceMessageType, object>("despatchAdvice", "application/xml", advice); } }
/// <summary> /// The issue despactch advice message will insert a new shipped order into the TImR system. /// </summary> public void IssueDespatchAdvice(DespatchAdviceMessageType advice) { if (advice == null || advice.despatchAdvice == null) { throw new InvalidOperationException("Invalid message sent"); } // TODO: Validate the standard header // Loop Bundle orderTransaction = new Bundle(); foreach (var adv in advice.despatchAdvice) { // Has this already been created? Place sourceLocation = this.m_gs1Util.GetLocation(adv.shipper), destinationLocation = this.m_gs1Util.GetLocation(adv.receiver); if (sourceLocation == null) { throw new KeyNotFoundException($"Shipper location not found"); } else if (destinationLocation == null) { throw new KeyNotFoundException($"Receiver location not found"); } // Find the original order which this despatch advice is fulfilling Act orderRequestAct = null; if (adv.orderResponse != null || adv.purchaseOrder != null) { orderRequestAct = this.m_gs1Util.GetOrder(adv.orderResponse ?? adv.purchaseOrder, ActMoodKeys.Request); if (orderRequestAct != null) // Orderless despatch! { // If the original order request is not comlete, then complete it orderRequestAct.StatusConceptKey = StatusKeys.Completed; orderTransaction.Add(orderRequestAct); } } // Find the author of the shipment var oidService = ApplicationContext.Current.GetService <IOidRegistrarService>(); var gln = oidService.GetOid("GLN"); var issuingAuthority = oidService.FindData($"{gln.Oid}.{adv.despatchAdviceIdentification.contentOwner?.gln}"); if (issuingAuthority == null) { issuingAuthority = oidService.GetOid(this.m_configuration.DefaultContentOwnerAssigningAuthority); } if (issuingAuthority == null) { throw new KeyNotFoundException("Cannot find default issuing authority for advice identification. Please configure a valid OID"); } int tr = 0; var existing = this.m_actRepository.Find <Act>(o => o.Identifiers.Any(i => i.Authority.DomainName == issuingAuthority.Mnemonic && i.Value == adv.despatchAdviceIdentification.entityIdentification), 0, 1, out tr); if (existing.Any()) { this.m_tracer.TraceWarning("Duplicate despatch {0} will be ignored", adv.despatchAdviceIdentification.entityIdentification); continue; } // Now we want to create a new Supply act which that fulfills the old act Act fulfillAct = new Act() { CreationTime = DateTimeOffset.Now, MoodConceptKey = ActMoodKeys.Eventoccurrence, ClassConceptKey = ActClassKeys.Supply, StatusConceptKey = StatusKeys.Active, TypeConceptKey = Guid.Parse("14d69b32-f6c4-4a49-a527-a74893dbcf4a"), // Order ActTime = adv.despatchInformation.despatchDateTimeSpecified ? adv.despatchInformation.despatchDateTime : DateTime.Now, Extensions = new List <ActExtension>() { new ActExtension(Gs1ModelExtensions.ActualShipmentDate, typeof(DateExtensionHandler), adv.despatchInformation.actualShipDateTime), new ActExtension(Gs1ModelExtensions.ExpectedDeliveryDate, typeof(DateExtensionHandler), adv.despatchInformation.estimatedDeliveryDateTime) }, Tags = new List <ActTag>() { new ActTag("orderNumber", adv.despatchAdviceIdentification.entityIdentification), new ActTag("orderStatus", "shipped"), new ActTag("http://openiz.org/tags/contrib/importedData", "true") }, Identifiers = new List <ActIdentifier>() { new ActIdentifier(new AssigningAuthority(issuingAuthority.Mnemonic, issuingAuthority.Name, issuingAuthority.Oid), adv.despatchAdviceIdentification.entityIdentification) }, Participations = new List <ActParticipation>() { // TODO: Author // TODO: Performer new ActParticipation(ActParticipationKey.Location, sourceLocation.Key), new ActParticipation(ActParticipationKey.Destination, destinationLocation.Key) } }; orderTransaction.Add(fulfillAct); // Fullfillment if (orderRequestAct != null) { fulfillAct.Relationships = new List <ActRelationship>() { new ActRelationship(ActRelationshipTypeKeys.Fulfills, orderRequestAct.Key) } } ; // Now add participations for each material in the despatch foreach (var dal in adv.despatchAdviceLogisticUnit) { foreach (var line in dal.despatchAdviceLineItem) { if (line.despatchedQuantity.measurementUnitCode != "dose" && line.despatchedQuantity.measurementUnitCode != "unit") { throw new InvalidOperationException("Despatched quantity must be reported in units or doses"); } var material = this.m_gs1Util.GetManufacturedMaterial(line.transactionalTradeItem, this.m_configuration.AutoCreateMaterials); // Add a participation fulfillAct.Participations.Add(new ActParticipation(ActParticipationKey.Consumable, material.Key) { Quantity = (int)line.despatchedQuantity.Value }); } } } // insert transaction if (orderTransaction.Item.Count > 0) { try { ApplicationContext.Current.GetService <IBatchRepositoryService>().Insert(orderTransaction); } catch (Exception e) { this.m_tracer.TraceError("Error issuing despatch advice: {0}", e); throw new Exception($"Error issuing despatch advice: {e.Message}", e); } } }