class ImportSveaFileService_Custom extends SysOperationServiceBase { private Map companyLedgerJournalTableMap; public void run(ImportSveaFileContract_Custom _contract) { if (_contract.parmStorageResult() != conNull()) { FileUploadTemporaryStorageResult fileUploadResult = new FileUploadTemporaryStorageResult(); fileUploadResult.unpack(_contract.parmStorageResult()); if (fileUploadResult != null) { try { System.IO.Stream fileStream = File::UseFileFromURL(fileUploadResult.getDownloadUrl()); XmlDocument doc; XmlNodeList data; XmlElement nodeTable; XmlElement nodeId; XMLParseError xmlError; doc = XmlDocument::newFromStream(fileStream); int lineNum = 0; real totalamountHeader, totalamountTrans = 0; real totalDiscfee, totalAdmfee; CurrencyCode currencyCode; // Verify XML Document Structure xmlError = doc.parseError(); if(xmlError && xmlError.errorCode() != 0) { throw error(strFmt("XML Error: %1", xmlError.reason())); } BankAccountTable bankAccountTable = BankAccountTable::find(_contract.parmBankAccount()); LedgerJournalTable ledgerJournalTable = LedgerJournalTable::find(_contract.parmJournalId()); data = doc.selectNodes('//'+"header"); nodeTable = data.nextNode(); while (nodeTable) { nodeId = nodeTable.selectSingleNode("totalamount"); totalamountHeader = str2Num(nodeId.text()); nodeId = nodeTable.selectSingleNode("batchcurrency"); currencyCode = nodeId.text(); nodeTable = data.nextNode(); } data = doc.selectNodes('//'+"transaction"); nodeTable = data.nextNode(); //LedgerJournalTrans custLedgerJournalTrans; //RecordInsertList recordInsertListLedgerJournalTrans = new RecordInsertList(tableNum(LedgerJournalTrans)); while (nodeTable) { ttsbegin; real discfee, admfee, invoiceamount; LedgerJournalTrans custLedgerJournalTrans; custLedgerJournalTrans.JournalNum = ledgerJournalTable.JournalNum; custLedgerJournalTrans.LineNum = lineNum; lineNum++; Voucher voucher; NumberSeq numberSeq; numberSeq = NumberSeq::newGetVoucherFromId(ledgerJournalTable.NumberSequenceTable); voucher = numberSeq.voucher(); custLedgerJournalTrans.Voucher = voucher; custLedgerJournalTrans.CurrencyCode = currencyCode; custLedgerJournalTrans.AccountType = LedgerJournalACType::Cust; custLedgerJournalTrans.TransactionType = LedgerTransType::Payment; nodeId = nodeTable.selectSingleNode("invoicedate"); custLedgerJournalTrans.TransDate = str2Date(nodeId.text(),321); nodeId = nodeTable.selectSingleNode("customernumber"); CustAccount custAccountNum = CustTable::findRecId(str2recId(nodeId.text())).AccountNum; custLedgerJournalTrans.parmAccount(custAccountNum, LedgerJournalACType::Cust); CustTable custTable = CustTable::find(custLedgerJournalTrans.parmAccount()); if (custTable) { custLedgerJournalTrans.DefaultDimension = custTable.DefaultDimension; custLedgerJournalTrans.Payment = custTable.PaymTermId; } nodeId = nodeTable.selectSingleNode("invoiceid"); custLedgerJournalTrans.MarkedInvoice = nodeId.text(); custLedgerJournalTrans.MarkedInvoiceCompany = curExt(); nodeId = nodeTable.selectSingleNode("invoiceamount"); invoiceamount = str2Num(nodeId.text()); custLedgerJournalTrans.amountCur2DebCred(invoiceamount * -1); custLedgerJournalTrans.OffsetAccountType = LedgerJournalACType::Bank; custLedgerJournalTrans.OffsetLedgerDimension = bankAccountTable.LedgerDimension; custLedgerJournalTrans.Triangulation = Currency::triangulation(custLedgerJournalTrans.CurrencyCode, custLedgerJournalTrans.TransDate); custLedgerJournalTrans.ExchRate = ExchangeRateHelper::exchRate(custLedgerJournalTrans.CurrencyCode, custLedgerJournalTrans.TransDate); custLedgerJournalTrans.ExchRateSecond = ExchangeRateHelper::exchRateSecond(custLedgerJournalTrans.CurrencyCode, custLedgerJournalTrans.TransDate); custLedgerJournalTrans.PostingProfile = CustParameters::find().PostingProfile; custLedgerJournalTrans.BankCentralBankPurposeCode = custTable.BankCentralBankPurposeCode; custLedgerJournalTrans.BankCentralBankPurposeText = custTable.BankCentralBankPurposeText; custLedgerJournalTrans.Txt = this.determineTransactionText(LedgerTransTxt::CustVendNetVendor, custLedgerJournalTrans); custLedgerJournalTrans.OffsetTxt = this.determineTransactionText(LedgerTransTxt::CustVendNetLedger, custLedgerJournalTrans); nodeId = nodeTable.selectSingleNode("discfee"); discfee = str2Num(nodeId.text()); nodeId = nodeTable.selectSingleNode("admfee"); admfee = str2Num(nodeId.text()); CustInvoiceJour CustInvoiceJour; select firstonly custInvoiceJour where custInvoiceJour.InvoiceId == custLedgerJournalTrans.MarkedInvoice && custInvoiceJour.InvoiceDate == custLedgerJournalTrans.TransDate && custInvoiceJour.InvoiceAccount == custTable.AccountNum; if (invoiceamount != custInvoiceJour.InvoiceAmount) { warning(strFmt("Invoice amount mismatch on %1", custInvoiceJour.InvoiceId)); } totalamountTrans += invoiceamount; totalDiscfee += discfee; totalAdmfee += admfee; nodeTable = data.nextNode(); custLedgerJournalTrans.insert(); LedgerJournalEngine_CustPayment::updateMarkedInvoiceSpecTrans(custLedgerJournalTrans); ttscommit; //recordInsertListLedgerJournalTrans.add(custLedgerJournalTrans); } // recordInsertListLedgerJournalTrans.insertDatabase(); info(strFmt("Total amount from file: %1 - total from journal: %2 -Total discfee: %3 – Total admfee: %4",totalamountHeader, totalamountTrans, totalDiscfee, totalAdmfee)); } catch (Exception::Error) { error("@RET433"); } } } } private TransactionTextLarge determineTransactionText( LedgerTransTxt _ledgerTransTxt, LedgerJournalTrans _ledgerJournalTrans) { TransactionTxt transactionTxt = TransactionTxt::construct(); transactionTxt.setType(_ledgerTransTxt); transactionTxt.setVoucher(_ledgerJournalTrans.Voucher); transactionTxt.setDate(_ledgerJournalTrans.TransDate); transactionTxt.setKey1(_ledgerJournalTrans.parmAccount()); transactionTxt.setFormLetter(_ledgerJournalTrans.Voucher); return transactionTxt.txt(); } } =========== class ImportSveaFileUIBuilder_Custom extends SysOperationAutomaticUIBuilder { private str availableTypes = ".xml"; private const str OkButtonName = 'CommandButton'; private const str FileUploadName = 'FileUpload'; ImportSveaFileContract_Custom contract; /// <summary> /// Overriden the <c>postBuild</c> method to add a <c>FileUpload</c> control /// </summary> public void postBuild() { DialogGroup dialogGroup; FormBuildControl formBuildControl; FileUploadBuild dialogFileUpload; super(); contract = this.dataContractObject(); dialogGroup = dialog.addGroup("File path"); formBuildControl = dialog.formBuildDesign().control(dialogGroup.name()); dialogFileUpload = formBuildControl.addControlEx(classstr(FileUpload), FileUploadName); dialogFileUpload.style(FileUploadStyle::MinimalWithFilename); dialogFileUpload.baseFileUploadStrategyClassName(classstr(FileUploadTemporaryStorageStrategy)); dialogFileUpload.fileTypesAccepted(availableTypes); dialogFileUpload.fileNameLabel("@SYS308842"); } /// <summary> /// Subscribes events to the dialog form /// </summary> /// <param name = "_formRun">The instance of the dialog form</param> private void dialogEventsSubscribe(FormRun _formRun) { FileUpload fileUpload = _formRun.control(_formRun.controlId(FileUploadName)); fileUpload.notifyUploadCompleted += eventhandler(this.uploadCompleted); fileUpload.notifyUploadAttemptStarted += eventhandler(this.uploadStarted); _formRun.onClosing += eventhandler(this.dialogClosing); } /// <summary> /// Executes logic for unsubscribing the registered events on the form /// </summary> /// <param name = "sender"></param> /// <param name = "e"></param> [SuppressBPWarningAttribute('BPParameterNotUsed', 'This is event parameter not required to use')] private void dialogClosing(xFormRun sender, FormEventArgs e) { this.dialogEventsUnsubscribe(sender as FormRun); } /// <summary> /// Unsubscribes events from the dialog form /// </summary> /// <param name = "_formRun">The instance of the dialog form</param> private void dialogEventsUnsubscribe(FormRun _formRun) { FileUpload fileUpload = _formRun.control(_formRun.controlId(FileUploadName)); fileUpload.notifyUploadCompleted -= eventhandler(this.uploadCompleted); fileUpload.notifyUploadAttemptStarted -= eventhandler(this.uploadStarted); _formRun.onClosing -= eventhandler(this.dialogClosing); } /// <summary> /// Executes additional logic once the upload of the file is completed /// </summary> protected void uploadCompleted() { var formRun = this.dialog().dialogForm().formRun(); FileUpload fileUpload = formRun.control(formRun.controlId(FileUploadName)); FileUploadTemporaryStorageResult uploadResult = fileUpload.getFileUploadResult(); if (uploadResult != null && uploadResult.getUploadStatus()) { contract.parmStorageResult(uploadResult.pack()); } this.setDialogOkButtonEnabled(formRun, true); } /// <summary> /// Additional logic which is executed once the upload of the file has started /// </summary> private void uploadStarted() { var formRun = this.dialog().dialogForm().formRun(); this.setDialogOkButtonEnabled(formRun, false); } /// <summary> /// Enables/Disables the OK button of the dialog /// </summary> /// <param name = "_formRun">The instance of the dialog form</param> /// <param name = "_isEnabled">Should the OK button be enabled?</param> protected void setDialogOkButtonEnabled(FormRun _formRun, boolean _isEnabled) { FormControl okButtonControl = _formRun.control(_formRun.controlId(OkButtonName)); if (okButtonControl) { okButtonControl.enabled(_isEnabled); } } /// <summary> /// Override of the <c>postRun</c> method in order to add events subscriptions /// </summary> public void postRun() { super(); FormRun formRun = this.dialog().dialogForm().formRun(); this.dialogEventsSubscribe(formRun); this.setDialogOkButtonEnabled(formRun, false); } } === class ImportSveaFileController_Custom extends SysOperationServiceController { /// <summary> /// Constructs an instance /// </summary> /// <returns>an instance of class</returns> public static ImportSveaFileController_Custom construct(Args _args) { ImportSveaFileController_Custom controller = new ImportSveaFileController_Custom(classstr(ImportSveaFileService_Custom), methodstr(ImportSveaFileService_Custom, run), SysOperationExecutionMode::Synchronous); controller.parmArgs(_args); controller.initializeContract(controller); return controller; } /// <summary> /// Initializes the contract parameters. /// </summary> /// <param name = "_controller">An instance of the <c>CAMPeriodCalculationController</c> whose contract to initialize.</param> protected void initializeContract(ImportSveaFileController_Custom _controller) { LedgerJournalTable ledgerJournalTable = this.parmArgs().record(); if (ledgerJournalTable) { ImportSveaFileContract_Custom contract = _controller.getDataContractObject() as ImportSveaFileContract_Custom; if (contract) { contract.parmJournalId(ledgerJournalTable.JournalNum); } } } /// <summary> /// Instantiate controller. /// </summary> //protected void new() //{ // super(classStr(ImportSveaFileService_Custom), // methodStr(ImportSveaFileService_Custom,run )); // this.parmDialogCaption("Import Svea file into payment journal"); //} /// <summary> /// Runs the class with the specified arguments. /// </summary> /// <param name = "_args">The specified arguments.</param> public static void main(Args _args) { ImportSveaFileController_Custom::construct(_args).startOperation(); //ImportSveaFileController_Custom controller = ImportSveaFileController_Custom::newFromArgs(); //controller.parmExecutionMode(SysOperationExecutionMode::Synchronous); //controller.startOperation(); } /// <summary> /// Instantiate and initialize controller class. /// </summary> /// <returns> /// returns controller class. /// </returns> //public static ImportSveaFileController_Custom newFromArgs() //{ // ImportSveaFileController_Custom controller = ImportSveaFileController_Custom::construct(); // return controller; //} } ==== [DataContractAttribute, SysOperationContractProcessing(classStr(ImportSveaFileUIBuilder_Custom))] class ImportSveaFileContract_Custom { LedgerJournalId journalId; CompanyBankAccountId bankAccount; container storageResult; /// <summary> /// Get/Set the email address /// </summary> /// <param name = "_emailAddress">email address</param> /// <returns>email address</returns> [DataMemberAttribute, SysOperationLabelAttribute(literalStr("Bank account")), SysOperationDisplayOrderAttribute('1')] public CompanyBankAccountId parmBankAccount(CompanyBankAccountId _bankAccount = bankAccount) { bankAccount = _bankAccount; return bankAccount; } /// <summary> /// Get/Set the email address /// </summary> /// <param name = "_emailAddress">email address</param> /// <returns>email address</returns> [DataMemberAttribute, SysOperationLabelAttribute(literalStr("Journal num")), SysOperationDisplayOrderAttribute('3'), SysOperationControlVisibility(false)] public LedgerJournalId parmJournalId(LedgerJournalId _journalId = journalId) { journalId = _journalId; return journalId; } /// <summary> /// Parameter method which holds values of the packed variables from <c>FileUploadTemporaryStorageResult</c> class /// </summary> /// <param name = "_storageResult">Packed instance of <c>FileUploadTemporaryStorageResult</c> class</param> /// <returns>Container with packed values</returns> [DataMemberAttribute('StorageResult'), SysOperationDisplayOrderAttribute('2')] public container parmStorageResult(container _storageResult = storageResult) { storageResult = _storageResult; return storageResult; } }
This blog is contains coding reference related to Microsoft AX 2012 and D365 finance and operations and Power platform
Friday, December 1, 2023
Sysoperation framework with file upload and UI builder D365FO
Subscribe to:
Post Comments (Atom)
No comments:
Post a Comment