Monday, 23 January 2023

A till on the SAP platform

I recently completed a two-month project to build a till solution in SAP. In summary, it went really well. The effort estimate and timeline were approved without much debate and we delivered accordingly. There was no PM, just a small team of senior SAP consultants and a business analyst from the customer who no doubt had a few meetings with the budget owner but we didn’t notice as there were no concerns worth discussing. I know full well that for decades people have reeled against writing bespoke software, but here we have proven that there is a way to deliver bespoke software well, affordably and reliably whilst delighting the users. We didn’t have a specification signed in blood, in fact, we didn’t use any Word documents at all. But I’ll come to that. 

A bit of background

Our client has several shops that sell both products off the shelve but also a lot of products that are stocked in a warehouse and require cutting/sawing/drilling etc… as part of the sales process.

The shops were using an off-the-shelve till system, not integrated with the SAP system nor with the payment terminals. The till operator had the error-prone task of keying everything in and the back office was forever trying to reconcile the cash book and the bank statements to the financial accounts.

But my client had S4/HANA and Fiori. Hence the obvious question was to integrate the till and the payment terminals with SAP. Something like this:


The big issue was that SAP does not have a till solution.

But we didn’t start from scratch. Data-wise, SAP already had customers, products, stock and prices. Warehouse management processes had already been implemented. Configuration-wise, the order types and invoice types existed as well, except for the 'till ticket' for which we created a new billing document type (a pro-forma invoice). The payment terminals were available but operating in standalone modus so they had to be connected to the internet and reconfigured. The SAP CPI platform was available for integration with Worldline.

The design phase

We started with a simple question from the client: “Can we capture the payments directly in SAP? Basically, a button in the order entry screen? And can you send the payment instruction to the payment terminal from SAP so we don’t have to key it in manually?” The client had formed an idea of the effort involved.

We had a conversation with Worldline who confirmed that integration of the payment terminals via an API was indeed possible, providing we let them validate our solution.

From increasingly detailed corridor-style conversations, I formed an idea of what a till screen should look like and I did a mock-up in pptx to prepare for the design thinking session. During that session, whilst people were discussing requirements, I refined the pptx. By the end of the session, the design was agreed based on the mock-up. Quite a few new requirements came to light.

I then proceeded to make an xlsx list of all build components that were required. I then estimated each line in the xlsx including testing time, go-live cutover, documentation, etc. I broke the build down to enough detail to ensure that no single item on the list was more than a few days effort. When I added the detailed estimates together, I came out 40% higher than what the client had had in mind, but this was acceptable given the additional features we had agreed upon.

And with that, the design phase was over. It was time to start building.


Technically, I decided on the following approach:

1) An ABAP report (from the area of dinosaurs, I know) with a dynpro screen (idem) to represent the till, a transaction code to call the report and a Fiori tile to call the transaction code. ABAP dynpro is very well known, easy to use and lots of consultants can find their way around it. Fiori Apps are a whole different cattle of complicated fish especially if you want to deviate from the standard screen layout templates which was inevitable in this case.

2) New database tables: to hold the shops, the payment terminals, the customers, the link between the orders and the till, the payments and the link between payments and orders.

3) ABAP classes to represent the business entities: a till, a customer, a cashbook, a till ticket, an order, a payment and a payment terminal.

4) ABAP classes for reporting (model/view pairs): customers, orders, order line details, payments, terminals and payments of orders. These classes provide quick ways to report on the new database tables. The view classes are subclasses of a generic view class that hides the complexities of the standard CL_GUI_ALV_GRID. The model classes are subclasses of a generic model class, each implementing their own data selection. The model and view classes are automatically picked up by a reporting framework that makes it possible to place several reports on the screen simultaneously.

5) Proxy objects generated from WSDL files for real-time synchronous integration with Worldline via CPI. Integration flows in CPI that pass data back and forth between the SAP backend and the Worldline server.

6) A Fiori catalog and group containing the till tile. Two user roles per shop: one for reporting and one for the till itself.

The integration with Worldline went very smoothly thanks to the available expertise in the team, and the successful validation was a confidence booster knowing our solution was solid from the word go.

The build phase

The build consisted of a step by step implementation of the build elements listed in the xlsx. Every now and then, I consulted the other consultants and demo’ed the till screen to gather more detailed feedback. The fact that the client could follow the progress created the confidence needed for me to work without much supervision. The deadline was reasonably crazy and I worked through several weekends. But I knew it wasn’t for very long, so…

The ABAP code is clean

Clean code is a big deal. And I am a strong believer. So…. This is my personal interpretation which I applied rigorously.

No code block is longer than 50 lines. (I hate scrolling and 50 lines of code fits on my monitor). There are no static classes and hardly any static methods. The class methods each perform one single function and the name of each method is carefully chosen to be unambiguous. The largest number of parameters passed to any method is 3 (mostly it is 1) making it obvious what a method does. The view classes do not have any attributes, the model classes have only the report filters as attributes. The other classes usually have 1 or 2 attributes, no more. The method names are short and contain maximum one verb and sometimes a noun. All these elements make for very readable and maintainable code. The only non-object oriented element was the 29 line ABAP report (see below). putting logic in classes like I did makes codes maximally reusable, testable and consistent.

This solution should pose no upgrade issues. Only a few enhancements were added to pass data from the till screen to the sales order entry program (where there was no standard way of achieving that). But these are very simple and can be easily validated during an upgrade project.

The single till screen contains many functions:

  • A list of customers currently in the shop (ALV). The user can select one customer to process further
  • A list of orders currently processed in the shop (ALV).  
  • Address, invoice details and credit status of the currently selected customer
  • Buttons to 'welcome' a customer and to let a customer 'depart'
  • Buttons to start order entry (3 different types of orders)
  • Buttons to capture two types of payments
  • Buttons to produce and print the till ticket / invoice (depending on the customer profile)
  • Buttons to look for pre-existing orders, created outside of the till
  • A button to create a new customer profile
  • A button to search for a customer profile
  • A button to check the payment status (with Worldline - only in case of temporary comms issues)
  • The due amount and the amount of change (in case of cash payment)
  • A popup to select the payment terminal and optionally overwrite the payment amount
Buttons that are not relevant to the situation of the till at a given moment, are disabled or completely hidden, making the screen intuitive and 'as simple as possible'
Despite this, the till ('kassa' in Dutch) program itself is only 29 lines long:


I’m only including this here to demonstrate that it is possible to hide complexity by structuring code well. 

Because of the structure and cleanliness of the code, I am confident that 95% of the code will never ever need to be looked at again.

My conclusion

I choose well established technologies (you may argue it’s the stuff of dinosaurs but it works!) which made the build easy to estimate, the solution technically simple and thus easy to maintain. Everything was built in SAP GUI, no need for Eclipse or any other build environment or software. 

The users enjoy using the till because the screen behaves exactly as they expect it to, using their terminology and only providing them with options that are relevant to the situation at each point in time. I believe building custom intuitive screens is a major contributor to any successful SAP implementation.




Tuesday, 13 September 2022

Another success story - Keeping the core clean

SAP is telling us SAP consultants to 'keep the core clean'. This means in short: don't change the SAP system in ways that will make it harder to maintain (think: upgrade/convert to the HANA platform/move to the cloud). Whilst promoting this mantra, SAP is steering its customers towards side-by-side builds in the cloud, using its middleware platform for integration.  Here is a story where we did keep the core clean without introducing external development platforms and middleware.

Our customer was running operations in 400+ locations. Each location was run by a subcontractor. The contractor was paid based on the number of transactions going through the till. Historically, most locations were actually operated by salaried employees. Hence the situation we encountered was one where an HR system had been modified over and over again to enable it to pay employees as well as contractors. The most obvious challenge was VAT, which is a completely alien concept in the world of HR. The HR system had gotten so 'dirty' that the cost of operating it had spiraled out of control and worst of all, it took 40 hours to calculate the payroll. This meant that there was no time to correct mistakes in the current month's run and all mistakes had to be carried to the next month to be corrected. This situation led to mistakes upon mistakes upon mistakes.

We looked to replace the HR system with a solution to calculate the pay in a cloud platform but realized the ongoing license cost would be considerable and the build would be out of our hands and hence very costly too. Additionally, we would need to send sensitive data into the cloud.

Our customer was already running the Netweaver platform. We decided to maximize its value. Our approach was to bring all transactions from the sites (1M+) into a central table every night via file upload. We then built some summarization logic into a second much smaller table, summarizing the transactions by type and location. This job takes about 12 minutes. A second job calculates the pay for each subcontractor based on the summarized transactions. The result is available in 15 minutes!(compared to 40 hours previously). The resulting figures are then passed to standard vendor invoices.

So in the end we built an ABAP solution in Netweaver that does exactly what's required and because it is bespoke, it was running with optimal performance. The solution sits on top of MM and FI and does not modify the core of SAP. In terms of upgrading or converting to HANA, this poses zero problem.

Tuesday, 6 September 2022

An SAP success story on keeping the core clean

 I often read that people question the concept of keeping the core clean with the argument that SAP does not cater for all variations of possible business processes.

Of course the argument is very valid. SAP does not cater for every possible business process variant. How could it? In my career I have encountered this issue many times and in a few cases I was lucky enough to be part of a strong team that overcame the issue without ‘dirtying the core’ of the SAP system (we didn’t call it that at the time). This blog is about one of those times.

I’ll call the customer H. H holds stock of very precious materials in consignment for its 200+ customers. These 200 customers trade their stock among each other without the stock actually physically moving. H charges its customers for looking after their stock and also for each trade they do. It is extremely important that H can tell at any point in time who owns each stock item. H’s customers can deliver more stock to H’s warehouse or they can collect stock from the warehouse. They announce these transports well ahead of time so they can be planned meticulously. H spends a fair bit of time reorganising the stock in the warehouse to optimise the operations. It has to be noted that moving a stock item is quite hard and the storage space is very valuable. It happens regularly that stock changes owner whilst being moved around in the warehouse at the same time. But for H it is absolutely key that at all times all stock items are accounted for in terms of owner and location.

We realised early on that we had a problem tying customers to stock in the way we needed. Standard SAP assumes that you are the owner of your stock, and rightfully so.

We decided that the best way was to use the following standard components:

- The SD and FI modules for customers, pricing and customer billing

- Project systems to tie the stock items to projects and enable us to move stock between customers (effectively between projects)

- MM, WM and Inventory management to keep track of stock location and stock items

The only thing we had to do non-standard was tie a customer to each project. And so the only user exit we implemented was to prevent users going into the PS module and interfering with the link between the project and its customer.

All user screens are bespoke and do only and exactly what H wants including a ton of validations and controls. Building screens and lists in SAP is not hard. ABAP was designed for that. The end users do not see a single SAP term, everything they see is in their domain language. They don’t know the system is using projects, that’s completely hidden.

The trades are stored in a bespoke ABAP table as nothing in standard SAP comes close to holding the information we were dealing with. An ALV list report with a few buttons were enough to manage the trades. 

Other than that, we developed zero enhancements, users exits, etc. It was heaven. All code is in the right place and squeaky clean. This system has now been moved to the HANA platform with zero hassle, because we kept the core clean.

There were some other things about this project that made it such a success.

At the beginning of the project we received specifications that were incomplete and confusing, as the customer with no knowledge of SAP’s capabilities and little to no IT project experience was desperately trying to define the solution in every minute detail…as instructed by top management. I’m glad to say, we managed to gently refocus the customer on telling us about their business and processes and stop worrying about the solution. Using weekly incremental demos we built the entire solution faster than anticipated. The bespoke screens proved to H that we were listening to them and had understood their needs. Trust grew between us and H and that is without a shadow of a doubt the number one ingredient for a successful IT implementation. The collaboration was fantastic. Worries about budgets and timelines slowly moved to the background.

Yes, we developed a fair amount of bespoke code. Many people fear this. I believe it was around week 5 that we were told that all stock was moved using pallets. The customer had failed to mention that as it was ‘obvious’ to them. The word pallet did not appear anywhere in the spec. Luckily because the ABAP code was organised around properly structured classes representing real business objects, we had little trouble inserting the concept of a pallet into what we had built so far.

In all the time that this solution has been in operation, there have only been a handful of helpdesk tickets for it, mostly on cosmetic things. Because the solution runs inside the existing SAP Netweaver/HANA server we saved a ton of time and money by not having to install/procure additional kit and build integrations. Perhaps this was an side-by-side solution built inside?

Sunday, 4 September 2022

When your customer wants you to implement workflow…

 I’m definitely not the 1st one to point this out. Sometimes you have to tell your customer ‘no’ and you have to tell them in the right way. The right way is to focus on the business need and ignore all else. Remember this when you get told to implement workflow. 

Companies don’t like to spend their money (on the wrong things) and any purchase will often be preceded by an approval process. But this is not what the consultant is told. The consultant is told: please implement a workflow for PO approval.

What are the business needs here? Well firstly expenditure must be controlled and no employee should be able to willy-nilly spend company money. There is a need for a process. For example: the employee will raise a purchase requisition, this will be converted into a purchase order by another employee and the purchase order will be approved (or rejected) by one or more other employees. A decent IT system can then handle the rest in the background: send the order to the supplier, inform the warehouse manager about the inbound goods, etc…

A second business need is a consequence of the first one: the approval process must be as efficient as possible. Well in fact, this is a requirement for all business processes.

Now it so happens that managers find approving PO’s a pain in the backside that they would rather get rid of, especially because they cannot control when the approval requests will come in and they are sometimes urgent. They even get them whilst on holiday! What a nuisance.

In my experience, a solid PO approval process starts like this.

1. No PO should be auto approved even if the system cannot derive an approver. SAP is guilty as charged. That issue has to be dealt with as a priority. A report should list all approvers and the scope of their approval. It should also show the gaps: situations where the system cannot find an approver for whatever reason.

2. There is a way to centrally monitor all unapproved POs, who the next approver is and how long the delay is in the approval process. Also, this report should be able to list approved POs, with delays and what/who caused the delays. Building this is not a task for the faint-hearted.

3. Once those 2 elements are in place and owned by the central procurement team, one could consider implementing workflow. Workflow isn’t all that sexy by the way. It simply means that the approver receives a notification, usually by email. 

But managers hate email. They get so much of it. They are thought in management seminars not to respond to email or do it infrequently, so their teams do not grow to expect quick answers any time of day or night. So then the IT department comes along and gives employees a mechanism to bombard managers with email that must not be ignored. Oh my.

But things get worse: in standard solutions offered by SAP, the manager does not see the full PO but only some summarised data. So to perform an approval, they need to click on a link that opens another app. What if the manager is sitting in an aeroplane or some other place without a decent internet connection? The nuisance just got a lot bigger! 

My recommendation is to start with the two monitoring reports mentioned above. Admin staff can use those to help the manager approve efficiently during their private meetings, maybe once or twice a week. In that case, there is no need to build anything else. But if you are going to bombard your managers with email, make sure the email gives full sight of the PO including who else already approved it. Ensure they do not need to open other apps or technology to respond. It should be a simple email response with one click on a button. That email can sit in their outbox until they are back online and is sent automatically without further ado. 



Sunday, 7 August 2022

Rant over. Let’s get to work


After my initial rant it’s time to start thinking constructively. I realize I’ve introduced a couple of topics at a very high level and I now need to come up with practical answers. I’ve spoken about code quality and that perhaps wages should be tied to that. I’ve spoken about the need to rate code quality. I have also spoken about standards and rules and providing feedback to the programmers which can help them become more proficient in writing readable and reusable code.

In my previous blog I talked about OO (object-oriented) coding as I believe it is the only way to elegantly structure business logic in small readable and reusable building blocks. I’ll introduce the 5 major elements that I believe lie at the foundation of readable reusable code.

1. I’ll start with the big one: code blocks must be single purpose and hence short. I believe a good guideline is 20 lines (each containing max one ABAP statement) maximum. To many programmers this may seem crazy small but I have very rarely needed more than that especially now that the ABAP language foresees so many powerful statements. Code blocks are: methods, function modules, forms, events in reports and macros (to be avoided completely).

2. Then there is the issue with global variables or variables in general. I often see long lists of variable declarations. They should be a thing of the past. Information should be kept in objects and in reusable data structures (I.e. not declared locally, but rather in the dictionary). In a class the only attributes should be the key identifiers of that instance. For example for a material class (remember a class represents a thing) the only attribute should be the material number as that is the unique identifier of a material. Another example could be a sales area (which is a core organizational structure in the sales module of SAP). The sales area is uniquely identified by the combination of the sales organization, the distribution channel and the division. In conclusion the sales area class should have three attributes or, even better, one attribute being a structure with three components. Reports should not have more than a handful (5 absolute max?) of global data declarations.

3. As discussed, business logic should work with business ‘things’ meaning instances of classes. Let me try to explain. We talked about the material class which is an object that represents a material. An instance of that class could be material 12345 or material ABC2. An instance is a specific example of a type of thing. In the same way sales area 4000/10/00 could be an instance (example) of a sales area. Good code will operate on instances. But it is also possible to write OO code that is static. Static code does not need instances and is therefore hard to understand and to be avoided at all cost.

4. Class methods should be single purpose and should have a maximum of three importing parameters (ideally none or one) and usually one returning parameter. I often see methods receiving more than five importing parameters because the programmer is not using classes properly. Classes are still often used as pseudo-function groups by programmers who have not grasped the principles of object-oriented thinking. Consequently, they still write procedural code within the object oriented framework, using tons of attributes and static code and frankly making a mockery of object orientation.

5. Because all code blocks are kept small and single purpose, it becomes possible to give them clear meaningful names. The same goes for the few variables and parameters (we should be using few). There has been a debate ever since the beginning of ABAP coding around prefixes. The big news here is that in almost all cases you don’t need them. They are clutter. If you see them get rid of them. How often have I seen variables like lt_tab. That means nothing. I would much rather see a variable named sales_orders. This not only tells me what information that variable holds but also that it is a table or a list because of the plural naming. And I do not need to make it clear that this is a local variable as I hardly use global variables anymore. The only exception is the global data structure needed to pass data to a screen.

Tuesday, 2 August 2022

OO. Ohhhhh. :(

OO stands for object oriented. It means that you write code around objects. For example:  An object could be a customer or supplier or a product or a delivery or a sales order or any other thing that has a unique identity. In Abap OO, when you create your own objects (called classes), their name has to start with the letter Y or Z. So a good name for a class could be ZCL_MATERIAL. A class name should contain a noun because it pertains to a thing (tangible or intangible) In SAP, the material is uniquely identified by means of a material number and this number should be kept in the attribute of that class. Any business logic that applies to materials can be kept inside the zcl_material class in logic blocks called methods. For example: You could have a method called get_stock_quantity. This method would return the number of pieces available of that material. A good method name contains one verb because it pertains to an action/operation/activity.

You can then do things like this

MyMaterial = new zcl_material( 12345 ).

If MyMaterial->get_stock_quantity( ) = 0

Message MyMaterial->get_name( ) && ‘ is out of stock’.

Endif.

This is reusable code consisting of reusable simple and single purpose building blocks. That is one of the key ingredients to high quality code. Code that is written in this style reads fairly easily and is understandable for testers and business consultants but also for the next programmer. This is extremely important to guarantee business continuity in a world where many programmers do short term assignments and then move on.

[WARNING: a rant follows]

If you are handed ABAP code that you cannot easily read, it is BAD code. Reject it! Do not put up with it. Tell the programmer to do a better job or if you are the next programmer, make it clear to your superiors that you have inherited BAD code and that enhancements to the code will take more time (times 3 is a good starting point) than one would typically expect and that you cannot give any guarantees on your work and that they will have to do extensive testing including regression testing. Do yourself and the rest of the SAP world a favour and speak up!


Something must be done

 After 25 years working on Abap code it’s got to be said: oh boy! is there a bunch of abysmal code out there.

There’s a lazy coder’s website and tik tok feed which is all very funny but also tragically close to reality. I can’t believe the average abapper gets paid as much as he/she does when de average quality of code I’ve come across is atrocious. Wouldn’t it be fair to tie code quality to wages? Well I think it’s the only way to stop abappers from being as sloppy and unprofessional as they are being today.

I’m obviously not out on a charm offensive with my peers. I’ve had to deal with so much garbage I cannot keep quiet any longer. Something must be done.

My current thinking is that we need to give IT managers, PM’s, testers, team leads, etc… a means to rate the ABAP code that they are handed, and provide feedback to the developer and even reject code that simply doesn’t live up to certain standards. I also think the abapper needs a place where he/she can skill up to raise the quality of the work.

So we need a place to upload code objects and perform quality inspection. The inspection must be based on a set of intelligent rules. So we need those rules.

Obviously I’m aware of the standard tools and whilst I can see the merit in using them and following the guidelines they provide, they are hugely insufficient in my opinion.