Because this background will (hopefully) inform the reader of where my thought processes are coming from.
I've been working with Jiwa since about 6.5.8, although there was quite a lull between all the work I did on 6.5.13 stabilising and our first Jiwa 7 upgrade, which I was involved in early 2017.
Those early forays into converting breakouts into plugins were 'entertaining', and a I went through a few revisions before I got to the system I'm using now.
Style-wise, I ended up working with many small plugins rather than one or two large ones. I found that there was a lot of 'Business Logic' overlap with the various UI components. For example, in the Sales Order Maintenance screen, I might need business logic from Sales, Debtors, Inventory, Purchasing and Creditors; and so, instead of duplicating code, I chose to maximise code re-use, and to use the 'Plugin Reference' feature extensively. This means that many of my plugins only use one of the "ApplicationManagerPlugin", "BusinessLogicPlugin" or "FormPlugin" sections. I also have ended up putting *most* custom fields and system settings into a single "Ryan's Custom Fields" plugin (as I do more customised display logic, that is likely to change, but since I'm currently only working with upgrades where they all end up in one plugin anyway, it's a bit easier to work with for now).
Most of my "business logic" plugins are comprised of a VB "Utilities Module" (initialised from an ApplicationManagerPlugin) and, where needed, a BusinessLogicPlugin.
The 'Utilities' module holds things like Extension methods that make doing stuff elsewhere easier. e.g.
- Code: Select all
<Extension()>
Public Function DebtorInGroup(debtor As JiwaApplication.Entities.Debtor.Debtor, GroupId As String) As Boolean
Return DebtorInGroup(debtor.RecID, GroupId)
End Function
Allows me to do this:
- Code: Select all
Public Const PartnerGroupID As String = "CB05438A39EC46F5BC1A"
...
If debtor.DebtorInGroup(PartnerGroupID) Then
' Do something Partner-y
End If
UI modules are mostly comprised of (surprise!) just a FormPlugin.
Structurally, to help me keep track of the reference hierarchy, all my plugin names start with a 3-digit number, with the first digit representing a 'layer': '0' = business logic, '2' = EDI-related items, '8' = UI, '9' = scheduled tasks. The second digit is about the 'module', so e.g. '0' = 'module neutral', '1' = Debtors/Creditors, '2' = Inventory, '3' = Sales, '4' = Purchasing. The last digit is just a number.
I also give all my plugins their own namespace, mostly so that they can all co-exist in the same VS project (more on that later).
The project I'm working on at the moment (~25 plugins all up) looks something like this (names have been changed to protect the
guilty innocent).
Plugin Name | Namespace | Modules | Jiwa classes | Dependencies | Notes |
000 - Custom Fields | <None> | <None> | CustomFieldPlugin | | (almost) all my custom fields. |
001 - Shared Library | Ryan | RyansSharedLibrary | ApplicationManagerPlugin, SystemSettingPlugin | | this module contains general-purpose helper functions. Things like error-logging, common custom field handling and system settings. |
010 - Debtor Library | Ryan.DebtorLibrary | RyansDebtorLibrary | ApplicationManagerPlugin | 001 | |
015 - Creditor Library | Ryan.CreditorLibrary | RyansCreditorLibrary | ApplicationManagerPlugin, BusinessLogicPlugin | 001 | |
020 - Inventory Library | Ryan.InventoryLibrary | RyansInventoryLibrary | ApplicationManagerPlugin, BusinessLogicPlugin | 001 | |
030 - Sales Order Library | Ryan.SalesOrderLibrary | RyansSalesOrderLibrary | ApplicationManagerPlugin, BusinessLogicPlugin | 001, 010 | |
040 - Purchase Order Library | Ryan.PurchaseOrderLibrary | RyansPurchaseOrderLibrary | ApplicationManagerPlugin, BusinessLogicPlugin | 001, 015, 030 | |
831 - Sales Order UI | Ryan.SalesOrderUI | | FormPlugin | 001, 010, 020, 030, 040 | |
841 - Purchase Order UI | Ryan.PurchaseOrderUI | | FormPlugin | 001, 020, 030, 040 | |
My plugin development workflow looks a bit like this:
- For a customer's Jiwa 7 implementation, I create a Visual Studio solution, with a project for each language that I'm using (VB and/or C#). I use an actual project file, but just 'opening a folder' might work just as well.
- I have some 'standard' utility plugins that I import into Jiwa, and then I add new plugins via the Jiwa UI
- I have a Microsoft Access database that queries the plugin table (using ODBC-linked tables), and exports the plugin code for all plugins with me as the author, to an 'export' folder (not the VS project folder); setting the file timestamp to match the 'LastSaved' time of the plugin.
- I use WinMerge (which is back under maintenance, which is good news), to compare the exported plugins to the VS plugins. Initially, this is just copying from the export folder to the project folder, and 'adding' the files to the project. But later, it can be merging in both directions, because sometimes I do minor editing within the Jiwa plugin editor while debugging, and then feed it back, while also working on files within VS.
- I maintain the plugins in Visual Studio.
- I use WinMerge again to move any changes back to the 'Export' folder
- The 'Export' folder now becomes an 'Import' folder, and I use the Access database to copy the plugin code back up to Jiwa. This updates the version number field, as well as the 'LastSaved' timestamp.
- Load Jiwa and fix any dependencies; whether they be plugin, assembly or embedded; restart Jiwa if needed.
- Test & debug in Jiwa
- Rinse and repeat
Notesfor the solution, an earlier approach I tried, which is probably technically closer to the way plugins work within Jiwa, was to create a project (and folder) for each plugin. This worked well, until I wanted to move code in-and-out of Jiwa in 'bulk' and compare Jiwa's code with my VS code. So I changed to one folder per language. I suspect this will change if we get some kind of Jiwa integration going with either VS or Git.