예제 #1
0
        public Error InsertOrUpdateDocumentTemplate(DocumentTemplateModel template, UserModel user, string lockGuid)
        {
            var error = validateModel(template);

            if (!error.IsError)
            {
                // Check that the lock is still current
                if (!db.IsLockStillValid(typeof(DocumentTemplate).ToString(), template.Id, lockGuid))
                {
                    error.SetError(EvolutionResources.errRecordChangedByAnotherUser, "TemplateName");
                }
                else
                {
                    DocumentTemplate temp = null;
                    if (template.Id != 0)
                    {
                        temp = db.FindDocumentTemplate(template.Id);
                    }
                    if (temp == null)
                    {
                        temp = new DocumentTemplate();
                    }

                    Mapper.Map <DocumentTemplateModel, DocumentTemplate>(template, temp);

                    db.InsertOrUpdateDocumentTemplate(temp);
                    template.Id = temp.Id;
                }
            }
            return(error);
        }
예제 #2
0
        public void DeleteDocumentTemplateTest()
        {
            // Get a test user
            var user        = GetTestUser();
            var testCompany = GetTestCompany(user);

            // Create a price level
            DocumentTemplateModel model = createDocumentTemplate(testCompany, DocumentTemplateCategory.Invoice, DocumentTemplateType.None);

            var error = LookupService.InsertOrUpdateDocumentTemplate(model, user, "");

            Assert.IsTrue(!error.IsError, error.Message);

            // Check that it was written
            var result = db.FindDocumentTemplate(model.Id);
            var test   = LookupService.MapToModel(result);

            AreEqual(model, test);

            // Now delete it
            LookupService.DeleteDocumentTemplate(model.Id);

            // And check that is was deleted
            result = db.FindDocumentTemplate(model.Id);
            Assert.IsTrue(result == null, "Error: A non-NULL value was returned when a NULL value was expected - record delete failed");
        }
예제 #3
0
 public TemplateCardViewModel(DocumentTemplateModel model, INavigationService navigator, ITemplatesService templatesService, ITelemetryService telemetryService)
 {
     _navigator        = navigator ?? throw new ArgumentNullException(nameof(navigator));
     _templatesService = templatesService;
     _telemetryService = telemetryService;
     Model             = model;
 }
예제 #4
0
        public async Task <IResponse> ShareDocumentTemplate(DocumentTemplateModel document, string fileName)
        {
            try
            {
                if (!fileName.EndsWith(".zip"))
                {
                    fileName += ".zip";
                }
                var rootFolder = Path.GetDirectoryName(fileName);
                if (rootFolder == null)
                {
                    return(Response.FromFailure("Failed to determine directory to save file", ResponseCode.FileNotFound));
                }

                var zipDirectory = Path.Combine(rootFolder, "zip");

                var sourceTemplateFile = $"{DocumentTemplatesDirectoryName}\\{document.Id}.{DocumentTemplateFileExtension}";
                var destTemplateFile   = $"{zipDirectory}\\{document.Id}.{DocumentTemplateFileExtension}";
                var sourceDocFile      = document.TemplateDetails.TemplateFilePath;
                var destDocFile        = $"{zipDirectory}\\{document.Id}.docx";

                await Task.Run(() =>
                {
                    try
                    {
                        Directory.CreateDirectory(zipDirectory);

                        File.Copy(sourceTemplateFile, destTemplateFile);
                        File.Copy(sourceDocFile, destDocFile);

                        ZipFile.CreateFromDirectory(zipDirectory, fileName);
                    }
                    finally
                    {
                        if (Directory.Exists(zipDirectory))
                        {
                            if (File.Exists(destTemplateFile))
                            {
                                File.Delete(destTemplateFile);
                            }

                            if (File.Exists(destDocFile))
                            {
                                File.Delete(destDocFile);
                            }
                            Directory.Delete(zipDirectory);
                        }
                    }
                });

                return(Response.FromSuccess());
            }
            catch (Exception ex)
            {
                return(Response.FromException($"Failed to share template {document.TemplateDetails.Name}", ex));
            }
        }
예제 #5
0
        public DocumentTemplateModel MapToModel(DocumentTemplate item)
        {
            DocumentTemplateModel model = null;

            if (item != null)
            {
                model = Mapper.Map <DocumentTemplate, DocumentTemplateModel>(item);
                model.QualTemplateFile = GetConfigurationSetting("SiteFolder", "") + $"\\App_Data{item.TemplateFile}";
            }
            return(model);
        }
예제 #6
0
        public async Task <IResponse> SaveDocumentTemplate(DocumentTemplateModel document)
        {
            try
            {
                await SaveTemplate(document);

                return(Response.FromSuccess());
            }
            catch (Exception ex)
            {
                return(Response.FromException($"Failed to save template {document.TemplateDetails.Name}", ex));
            }
        }
예제 #7
0
        DocumentTemplateModel createDocumentTemplate(CompanyModel company, DocumentTemplateCategory templateCategory, DocumentTemplateType templateType)
        {
            DocumentTemplateModel model = new DocumentTemplateModel {
                Name             = RandomString(),
                Description      = RandomString(),
                TemplateCategory = templateCategory,
                TemplateType     = templateType,
                TemplateFile     = "",
                QualTemplateFile = GetAppSetting("SiteFolder", "") + $"\\App_Data",
                Enabled          = true
            };

            return(model);
        }
예제 #8
0
        public async Task <IResponse> DeleteDocumentTemplate(DocumentTemplateModel document)
        {
            try
            {
                var filePath = $"{DocumentTemplatesDirectoryName}\\{document.Id}.{DocumentTemplateFileExtension}";
                if (File.Exists(filePath))
                {
                    await Task.Run(() => File.Delete(filePath));
                }

                return(Response.FromSuccess());
            }
            catch (Exception ex)
            {
                return(Response.FromException($"Failed to delete template {document.TemplateDetails.Name}", ex));
            }
        }
예제 #9
0
        private Error validateModel(DocumentTemplateModel model)
        {
            var error = new Error();

            if (!error.IsError)
            {
                // Check if a record with the same name already exists
                var template = db.FindDocumentTemplate(model.Name);
                if (template != null &&                 // Record was found
                    ((template.Id == 0 ||               // when creating new or
                      template.Id != model.Id)))        // when updating existing
                {
                    error.SetError(EvolutionResources.errItemAlreadyExists, "Name");
                }
            }

            return(error);
        }
예제 #10
0
        private Task SaveTemplate(DocumentTemplateModel template) => Task.Run(() =>
        {
            if (!Directory.Exists(DocumentTemplatesDirectoryName))
            {
                Directory.CreateDirectory(DocumentTemplatesDirectoryName);
            }

            var templateDto = _mapper.Map <DocumentTemplateDto>(template);

            var documentJson = JsonConvert.SerializeObject(templateDto,
                                                           Formatting.Indented,
                                                           new JsonSerializerSettings
            {
                TypeNameHandling = TypeNameHandling.Objects,
                TypeNameAssemblyFormatHandling = TypeNameAssemblyFormatHandling.Simple
            });
            File.WriteAllText($"{DocumentTemplatesDirectoryName}\\{template.Id}.{DocumentTemplateFileExtension}", documentJson);
        });
예제 #11
0
        public Error CreatePickDocumentPdf(PickHeaderModel pickHeader, DocumentTemplateModel template,
                                           string pdfFile, bool showCancelledItems,
                                           ref string outputFile, int maxItems = Int32.MaxValue)
        {
            var error = new Error();

            string tempFile = MediaService.MediaService.GetTempFile(".html");

            if (string.IsNullOrEmpty(pdfFile))
            {
                outputFile = MediaService.MediaService.GetTempFile().FolderName() + "\\" + pickHeader.Id + "_" + DateTime.Now.ToString("yyyyMMddHHmmss") + ".pdf";
            }
            else
            {
                outputFile = pdfFile;
            }

            decimal subTotal     = 0;
            var     company      = CompanyService.FindCompanyModel(pickHeader.CompanyId == null ? 0 : pickHeader.CompanyId.Value);
            var     customer     = CustomerService.FindCustomerModel(pickHeader.CustomerId == null ? 0 : pickHeader.CustomerId.Value, company);
            var     paymentTerms = LookupService.FindPaymentTermModel(pickHeader.TermsID == null ? 0 : pickHeader.TermsID.Value);
            var     taxCode      = LookupService.FindTaxCodeModel(customer.TaxCodeId);
            var     currency     = LookupService.FindCurrencyModel(company.DefaultCurrencyID == null ? 0 : company.DefaultCurrencyID.Value);

            Dictionary <string, string>         headerProps = new Dictionary <string, string>();
            List <Dictionary <string, string> > records     = new List <Dictionary <string, string> >();

            AddCompanyInformation(company, headerProps);

            var pickDetailListModel = PickService.FindPickDetailListModel(company, pickHeader).FirstOrDefault();
            var sod = FindSalesOrderDetailModel(pickDetailListModel.SalesOrderDetailId);
            var soh = FindSalesOrderHeaderModel(sod.SalesOrderHeaderId, company);

            // RETAIL INVOICE/PACKING SLIP
            headerProps.AddProperty("ORDERDATE", formatDate(soh.OrderDate, company.DateFormat));
            headerProps.AddProperty("OURREF", soh.OrderNumber);

            // STANDARD PACKING SLIP
            headerProps.AddProperty("REFERENCENUMBER", soh.OrderNumber);
            headerProps.AddProperty("INVOICENUMBER", pickHeader.InvoiceNumber);
            headerProps.AddProperty("SALESDATE", formatDate(soh.OrderDate, company.DateFormat));
            headerProps.AddProperty("TERMS", paymentTerms.TermText); // ??

            headerProps.AddProperty("CUSTOMERCONTACT", pickHeader.CustomerContact);
            var address = pickHeader.ShipAddress1 + "<br/>";

            address += (!string.IsNullOrWhiteSpace(pickHeader.ShipAddress2)) ? pickHeader.ShipAddress2 + "<br/>" : "";
            address += (!string.IsNullOrWhiteSpace(pickHeader.ShipAddress3)) ? pickHeader.ShipAddress3 + "<br/>" : "";
            address += (!string.IsNullOrWhiteSpace(pickHeader.ShipAddress4)) ? pickHeader.ShipAddress4 + "<br/>" : "";
            address += pickHeader.ShipSuburb + " " + pickHeader.ShipState + " " + pickHeader.ShipPostcode + "<br/>";
            address += pickHeader.ShipCountry;
            headerProps.AddProperty("DELIVERYADDRESS", address);

            headerProps.AddProperty("ORDERNUMBER", soh.OrderNumber);
            headerProps.AddProperty("PURCHASEORDERNUMBER", soh.CustPO);

            // Add items
            int itemCount = 1;

            foreach (var pickDetail in PickService.FindPickDetailListModel(company, pickHeader))
            {
                var product = ProductService.FindProductModel(pickDetail.ProductId.Value, null, company, false);

                Dictionary <string, string> line = new Dictionary <string, string>();
                line.AddProperty("ORDERQTY", pickDetail.QtyToPick); // Correct?
                line.AddProperty("ITEMNUMBER", product.ItemNumber);
                line.AddProperty("DESCRIPTION", itemCount.ToString() + " " + sod.ProductDescription);

                // RETAIL INVOICE/PACKING SLIP
                var unitPriceExTax = sod.UnitPriceExTax.Value;
                var discountPc     = sod.DiscountPercent.Value;
                var linePrice      = (pickDetail.QtyToPick * unitPriceExTax - ((pickDetail.QtyToPick * unitPriceExTax) / 100 * discountPc)).Value;

                sod = FindSalesOrderDetailModel(pickDetail.SalesOrderDetailId);
                string allocated = AllocationService.GetExpectedShipdate(sod);
                if (allocated.Count() > 5)
                {
                    allocated = DateTimeOffset.Parse(allocated).ToString(company.DateFormat);
                }

                line.AddProperty("EXPSHIPDATE", allocated);
                line.AddProperty("LINEPRICE", sod.UnitPriceExTax.Value.ToString("#,##0.00"));
                subTotal += linePrice;

                records.Add(line);
                itemCount++;

                // STILL TO SHIP: TODO
            }

            // RETAIL INVOICE/PACKING SLIP
            headerProps.AddProperty("CURRENCYSYMBOL", currency.CurrencySymbol);
            headerProps.AddProperty("SALEAMOUNTEX", subTotal.ToString("#,##0.00"));
            headerProps.AddProperty("FREIGHT", pickHeader.FreightCost ?? 0);
            subTotal += Convert.ToDecimal(pickHeader.FreightCost);
            var subTotalIncGst = subTotal + (taxCode.TaxPercentageRate == null ? 0 : (subTotal / 100 * taxCode.TaxPercentageRate.Value));

            headerProps.AddProperty("SALEAMOUNTINC", subTotal.ToString("#,##0.00"));
            headerProps.AddProperty("GST", (subTotalIncGst - subTotal).ToString("#,##0.00"));
            headerProps.AddProperty("TAXNAME", taxCode.TaxCode);


            return(DocumentService.CreateDocumentPdf(headerProps, records, template.QualTemplateFile, outputFile, maxItems));
        }
예제 #12
0
 public string LockDocumentTemplate(DocumentTemplateModel model)
 {
     return(db.LockRecord(typeof(DocumentTemplate).ToString(), model.Id));
 }
예제 #13
0
        public DocumentTemplateModel Clone(DocumentTemplateModel item)
        {
            var newItem = Mapper.Map <DocumentTemplateModel, DocumentTemplateModel>(item);

            return(newItem);
        }
        public Error CreateOrderConfirmationPdf(SalesOrderHeaderModel soh, DocumentTemplateModel template,
                                                string pdfFile,
                                                bool showCancelledItems,
                                                ref string outputFile,
                                                int maxItems = Int32.MaxValue)
        {
            var error = new Error();

            string tempFile = MediaService.MediaService.GetTempFile(".html");

            if (string.IsNullOrEmpty(pdfFile))
            {
                outputFile = MediaService.MediaService.GetTempFile().FolderName() + "\\" + soh.OrderNumber + "_" + DateTime.Now.ToString("yyyyMMddHHmmss") + ".pdf";
            }
            else
            {
                outputFile = pdfFile;
            }

            // Insert the lines
            decimal subTotal       = 0,
                    subTotalIncGst = 0,
                    freightTotal   = 0;

            CompanyService.CompanyService companyService = new CompanyService.CompanyService(db);
            var company = companyService.FindCompanyModel(soh.CompanyId);

            CustomerService.CustomerService customerService = new CustomerService.CustomerService(db);
            var customer = customerService.FindCustomerModel(soh.CustomerId == null ? 0 : soh.CustomerId.Value,
                                                             company);

            var paymentTerms = LookupService.FindPaymentTermModel(soh.TermsId == null ? 0 : soh.TermsId.Value);

            var taxCode = LookupService.FindTaxCodeModel(customer.TaxCodeId);

            subTotalIncGst = subTotal + (taxCode.TaxPercentageRate == null ? 0 : (subTotal / 100 * taxCode.TaxPercentageRate.Value));

            var currency = LookupService.FindCurrencyModel(company.DefaultCurrencyID == null ? 0 : company.DefaultCurrencyID.Value);

            Dictionary <string, string>         headerProps = new Dictionary <string, string>();
            List <Dictionary <string, string> > records     = new List <Dictionary <string, string> >();

            AddCompanyInformation(company, headerProps);

            headerProps.AddProperty("ORDERNUMBER", soh.OrderNumber.ToString());
            headerProps.AddProperty("CUSTPO", soh.CustPO);
            headerProps.AddProperty("ORDERDATE", formatDate(soh.OrderDate, company.DateFormat));
            headerProps.AddProperty("PAYMENTTERMS", paymentTerms.TermText);

            var salesMgr = customerService.FindBrandCategorySalesPersonsModel(company, customer, soh.BrandCategoryId.Value, SalesPersonType.AccountAdmin).FirstOrDefault();

            if (salesMgr != null)
            {
                headerProps.AddProperty("ACCOUNTMANAGER", salesMgr.UserName);
            }
            else
            {
                headerProps.AddProperty("ACCOUNTMANAGER", "");
            }

            headerProps.AddProperty("CUSTOMERNAME", customer.Name);

            var contact = customerService.FindPrimaryCustomerContactsModel(customer)
                          .FirstOrDefault();

            headerProps.AddProperty("CUSTOMERCONTACT", contact.ContactFirstname + " " + contact.ContactSurname);

            var addrs = customerService.FindCurrentCustomerAddresses(customer, AddressType.Billing)
                        .FirstOrDefault();

            if (addrs == null)
            {
                addrs = new CustomerAddressModel();
            }

            headerProps.AddProperty("STREET", addrs.Street);
            headerProps.AddProperty("CITY", addrs.City);
            headerProps.AddProperty("STATE", addrs.State);
            headerProps.AddProperty("POSTCODE", addrs.Postcode);
            headerProps.AddProperty("COUNTRY", addrs.CountryName);
            headerProps.AddProperty("PHONENO", contact.ContactPhone1);
            headerProps.AddProperty("FAXNUMBER", contact.ContactFax);

            headerProps.AddProperty("DELIVERYADDRESS", soh.FullAddress.Replace("\r\n", "<br/>"));

            headerProps.AddProperty("TAXNAME", taxCode.TaxCode);
            headerProps.AddProperty("CURRENCYSYMBOL", currency.CurrencySymbol);

            var shipMethod = LookupService.FindLOVItemModel((soh.ShippingMethodId == null ? 0 : soh.ShippingMethodId.Value),
                                                            LOVName.ShippingMethod);

            headerProps.AddProperty("DELIVERYVIA", shipMethod.ItemText);

            string deliveryWindow = "";

            if (soh.DeliveryWindowOpen != null)
            {
                deliveryWindow = soh.DeliveryWindowOpen.Value.ToString(company.DateFormat);
            }
            if (soh.DeliveryWindowClose != null)
            {
                if (!string.IsNullOrEmpty(deliveryWindow))
                {
                    deliveryWindow += " - ";
                }
                deliveryWindow += soh.DeliveryWindowClose.Value.ToString(company.DateFormat);
            }
            headerProps.AddProperty("DELIVERYWINDOW", deliveryWindow);
            headerProps.AddProperty("SALESPERSON", soh.SalesPersonName);

            // Add items
            int itemCount = 1;

            foreach (var sod in FindSalesOrderDetailListModel(company, soh))
            {
                if (sod.LineStatusId != (int)SalesOrderLineStatus.Cancelled || showCancelledItems)
                {
                    decimal unitPriceExTax = (sod.UnitPriceExTax == null ? 0 : sod.UnitPriceExTax.Value);
                    decimal discountPc     = (sod.DiscountPercent == null ? 0 : sod.DiscountPercent.Value);
                    decimal linePrice      = (sod.OrderQty.Value * unitPriceExTax - ((sod.OrderQty.Value * unitPriceExTax) / 100 * discountPc));

                    Dictionary <string, string> line = new Dictionary <string, string>();
                    line.AddProperty("ORDERQTY", sod.OrderQty);

                    var product = ProductService.FindProductModel(sod.ProductId == null ? 0 : sod.ProductId.Value,
                                                                  null, company);
                    line.AddProperty("ITEMNUMBER", product.ItemNumber);
                    line.AddProperty("DESCRIPTION", itemCount.ToString() + " " + sod.ProductDescription);

                    var ecd = AllocationService.CalculateExpectedCompletionDate(sod);
                    if (ecd != null)
                    {
                        line.AddProperty("INSTOCK", ecd.Value.ToString(company.DateFormat));
                    }
                    else
                    {
                        line.AddProperty("INSTOCK", "");
                    }

                    line.AddProperty("UNITPRICEEXTAX", unitPriceExTax.ToString("#,##0.000"));
                    line.AddProperty("DISCOUNTPERCENT", discountPc.ToString("#,##0.00"));
                    line.AddProperty("LINEPRICE", linePrice.ToString("#,##0.000"));

                    subTotal += linePrice;

                    records.Add(line);
                    itemCount++;
                }
            }

            headerProps.AddProperty("TAXNAME", taxCode.TaxCode);
            headerProps.AddProperty("CURRENCYSYMBOL", currency.CurrencySymbol);

            headerProps.AddProperty("SALEAMOUNTEX", subTotal.ToString("#,##0.00"));

            freightTotal = CalculateEstimatedFreight(soh, customer);
            headerProps.AddProperty("ESTIMATEDFREIGHT", freightTotal.ToString("#,##0.00"));

            subTotal += freightTotal;

            subTotalIncGst = subTotal + (taxCode.TaxPercentageRate == null ? 0 : (subTotal / 100 * taxCode.TaxPercentageRate.Value));
            headerProps.AddProperty("SALEAMOUNTINC", subTotalIncGst.ToString("#,##0.00"));

            headerProps.AddProperty("GST", (subTotalIncGst - subTotal).ToString("#,##0.00"));

            return(DocumentService.CreateDocumentPdf(headerProps, records, template.QualTemplateFile, outputFile, maxItems));
        }
 public SummaryStepViewModel(DocumentTemplateModel model)
 {
     Model = model;
 }
예제 #16
0
        // This method is called by others in this module to provide a single point
        // fo creating sales-related PDFs
        private Error createSalesOrderPdf(SalesOrderHeaderModel soh, DocumentTemplateModel template,
                                          string pdfFile, bool showCancelledItems,
                                          ref string outputFile, int maxItems = Int32.MaxValue)
        {
            var error = new Error();

            string tempFile = MediaService.MediaService.GetTempFile(".html");

            if (string.IsNullOrEmpty(pdfFile))
            {
                outputFile = MediaService.MediaService.GetTempFile().FolderName() + "\\" + soh.OrderNumber + "_" + DateTime.Now.ToString("yyyyMMddHHmmss") + ".pdf";
            }
            else
            {
                outputFile = pdfFile;
            }

            // Insert the lines
            decimal subTotal       = 0,
                    subTotalIncGst = 0,
                    freightTotal   = 0;

            CompanyService.CompanyService companyService = new CompanyService.CompanyService(db);
            var company = companyService.FindCompanyModel(soh.CompanyId);

            CustomerService.CustomerService customerService = new CustomerService.CustomerService(db);
            var customer = customerService.FindCustomerModel(soh.CustomerId == null ? 0 : soh.CustomerId.Value,
                                                             company);

            var paymentTerms = LookupService.FindPaymentTermModel(soh.TermsId == null ? 0 : soh.TermsId.Value);

            var taxCode = LookupService.FindTaxCodeModel(customer.TaxCodeId);

            var currency = LookupService.FindCurrencyModel(company.DefaultCurrencyID == null ? 0 : company.DefaultCurrencyID.Value);

            Dictionary <string, string>         headerProps = new Dictionary <string, string>();
            List <Dictionary <string, string> > records     = new List <Dictionary <string, string> >();

            AddCompanyInformation(company, headerProps);

            headerProps.AddProperty("ORDERNUMBER", soh.OrderNumber.ToString());
            headerProps.AddProperty("CUSTPO", soh.CustPO);
            headerProps.AddProperty("ORDERDATE", formatDate(soh.OrderDate, company.DateFormat));
            headerProps.AddProperty("PAYMENTTERMS", paymentTerms.TermText);

            var salesMgr = customerService.FindBrandCategorySalesPersonsModel(company, customer, soh.BrandCategoryId.Value, SalesPersonType.AccountAdmin).FirstOrDefault();

            if (salesMgr != null)
            {
                headerProps.AddProperty("ACCOUNTMANAGER", salesMgr.UserName);
            }
            else
            {
                headerProps.AddProperty("ACCOUNTMANAGER", "");
            }

            headerProps.AddProperty("CUSTOMERNAME", customer.Name);

            var contact = customerService.FindPrimaryCustomerContactsModel(customer)
                          .FirstOrDefault();

            headerProps.AddProperty("CUSTOMERCONTACT", contact.ContactFirstname + " " + contact.ContactSurname);

            var addrs = customerService.FindCurrentCustomerAddresses(customer, AddressType.Billing)
                        .FirstOrDefault();

            if (addrs == null)
            {
                addrs = new CustomerAddressModel();
            }

            headerProps.AddProperty("STREET", addrs.Street);
            headerProps.AddProperty("CITY", addrs.City);
            headerProps.AddProperty("STATE", addrs.State);
            headerProps.AddProperty("POSTCODE", addrs.Postcode);
            headerProps.AddProperty("COUNTRY", addrs.CountryName);
            headerProps.AddProperty("PHONENO", contact.ContactPhone1);
            headerProps.AddProperty("FAXNUMBER", contact.ContactFax);

            headerProps.AddProperty("DELIVERYADDRESS", soh.FullAddress.Replace("\r\n", "<br/>"));

            headerProps.AddProperty("TAXNAME", taxCode.TaxCode);
            headerProps.AddProperty("CURRENCYSYMBOL", currency.CurrencySymbol);

            var shipMethod = LookupService.FindLOVItemModel((soh.ShippingMethodId == null ? 0 : soh.ShippingMethodId.Value),
                                                            LOVName.ShippingMethod);

            headerProps.AddProperty("DELIVERYVIA", shipMethod.ItemText);

            headerProps.AddProperty("REQUIREDDATE", (soh.RequiredDate == null ? "" : soh.RequiredDate.Value.ToString(company.DateFormat)));

            headerProps.AddProperty("SALESPERSON", soh.SalesPersonName);

            // Add items
            var barCodeService = new BarCodeService.BarCodeService(db);

            int itemCount = 1;

            foreach (var sod in FindSalesOrderDetailListModel(company, soh))
            {
                if ((template.TemplateType == DocumentTemplateType.SaleCancellation && sod.LineStatusId == (int)SalesOrderLineStatus.Cancelled) ||
                    (template.TemplateType != DocumentTemplateType.SaleCancellation && (sod.LineStatusId != (int)SalesOrderLineStatus.Cancelled || showCancelledItems)))
                {
                    decimal unitPriceExTax = (sod.UnitPriceExTax == null ? 0 : sod.UnitPriceExTax.Value);
                    decimal discountPc     = (sod.DiscountPercent == null ? 0 : sod.DiscountPercent.Value);
                    decimal orderQty       = (sod.OrderQty == null ? 0 : sod.OrderQty.Value);
                    decimal totalExTax     = unitPriceExTax * orderQty;
                    decimal linePrice      = (orderQty * unitPriceExTax - ((orderQty * unitPriceExTax) / 100 * discountPc));

                    Dictionary <string, string> line = new Dictionary <string, string>();
                    line.AddProperty("ORDERQTY", sod.OrderQty);

                    var    product    = ProductService.FindProductModel(sod.ProductId.Value, null, company, false);
                    string mediaImage = ProductService.GetProductImage(product, MediaSize.Large, 640, 480, false);
                    line.AddProperty("PRODUCTIMAGE", mediaImage);

                    line.AddProperty("ITEMNUMBER", product.ItemNumber);
                    line.AddProperty("ITEMNAME", product.ItemName);
                    line.AddProperty("DESCRIPTION", itemCount.ToString() + " " + sod.ProductDescription);
                    line.AddProperty("UNITPRICEEXTAX", unitPriceExTax.ToString("#,##0.00"));
                    line.AddProperty("TOTALEXTAX", totalExTax.ToString("#,##0.00"));
                    line.AddProperty("DISCOUNTPERCENT", discountPc.ToString("#,##0.00"));
                    line.AddProperty("LINEPRICE", linePrice.ToString("#,##0.00"));
                    //line.AddProperty("RRP", "");

                    line.AddProperty("BRANDNAME", product.BrandName);
                    line.AddProperty("CATEGORY", product.Category);     // NOT Brand Category

                    string dimensions = "";
                    if (product.Length != null && product.Width != null && product.Height != null)
                    {
                        if (company.UnitOfMeasure == UnitOfMeasure.Imperial)
                        {
                            dimensions  = product.Length.CmToInches().ToString();
                            dimensions += " x " + product.Width.CmToInches().ToString();
                            dimensions += " x " + product.Height.CmToInches().ToString();
                            dimensions += " " + company.LengthUnit;
                        }
                        else
                        {
                            dimensions  = product.Length.ToString();
                            dimensions += " x " + product.Width.ToString();
                            dimensions += " x " + product.Height.ToString();
                            dimensions += " " + company.LengthUnit;
                        }
                    }
                    line.AddProperty("DIMENSIONS", dimensions);

                    string barCodeFile = "";
                    if (!string.IsNullOrEmpty(product.BarCode))
                    {
                        barCodeFile = barCodeService.GetBarCode(product.BarCode, true);
                        if (!string.IsNullOrEmpty(barCodeFile))
                        {
                            line.AddProperty("BARCODE", $"<img src=\"{barCodeFile}\"/>");
                        }
                        else
                        {
                            line.AddProperty("BARCODE", "");
                        }
                    }
                    else
                    {
                        line.AddProperty("BARCODE", "");
                    }

                    line.AddProperty("MINSALEQTY", product.MinSaleQty.ToString());
                    line.AddProperty("MATERIAL", product.MaterialText);

                    subTotal += linePrice;

                    records.Add(line);
                    itemCount++;
                }
            }

            headerProps.AddProperty("TAXNAME", taxCode.TaxCode);
            headerProps.AddProperty("CURRENCYSYMBOL", currency.CurrencySymbol);
            headerProps.AddProperty("CURRENCYCODE", currency.CurrencyCode);

            headerProps.AddProperty("SALEAMOUNTEX", subTotal.ToString("#,##0.00"));

            if (template.TemplateType == DocumentTemplateType.ProFormaInvoice ||
                template.TemplateType == DocumentTemplateType.OrderConfirmation)
            {
                freightTotal = CalculateEstimatedFreight(soh, customer);
            }
            headerProps.AddProperty("ESTIMATEDFREIGHT", freightTotal.ToString("#,##0.00"));

            subTotal      += freightTotal;
            subTotalIncGst = subTotal + (taxCode.TaxPercentageRate == null ? 0 : (subTotal / 100 * taxCode.TaxPercentageRate.Value));

            headerProps.AddProperty("SALEAMOUNTINC", subTotalIncGst.ToString("#,##0.00"));

            headerProps.AddProperty("GST", (subTotalIncGst - subTotal).ToString("#,##0.00"));

            return(DocumentService.CreateDocumentPdf(headerProps, records, template.QualTemplateFile, outputFile, maxItems));
        }