Context
The case study company ran its purchasing and sales cycle on physical forms. Paper does two things badly at once. It keeps no record of who approved what, and it separates duties only as well as people remember to. A purchasing clerk and a sales clerk touch the same forms because the forms cannot tell them apart. The system had to move that cycle into software while making the separation explicit rather than customary.
My role
Bootcamp assignment at Maxy Academy, built individually. I designed the schema, the access model, the order and payment flows, and the gateway integration.
Process
- Modelled the access map as roles composed of named permissions rather than as fixed role checks, then declared the required permission on every route, so the entire access surface can be audited by reading one file.
- Separated viewing from changing as distinct permissions, because most roles in this domain need the first without the second. Purchasing sees items but does not edit them; sales owns customers and payments but never touches vendors.
- Applied the identical permissions to the token-authenticated API that the session-authenticated pages use, so a role cannot reach through the API what the interface refuses it. This is the mistake the design most needed to avoid.
- Integrated a payment gateway across three channels: hosted invoice, closed single-use virtual account, and e-wallet charge. Each channel payload and response shape is isolated in one gateway service, leaving the controllers to choose a channel and hand over validated input.
- Handled the fact that a virtual account never reports its own settlement, which makes the webhook the only path by which such a payment can be marked received. Verified the callback with a constant-time token comparison, and returned success on an unmatched reference so the gateway stops retrying a callback this system can never resolve.
- Extracted line pricing, discount, and tax arithmetic into a single support class shared by both order types, since purchase and sales lines price identically and duplicating the rule invites the two copies to drift.
- Archived records with a status flag instead of deleting them, because a document cycle that loses its own history is the problem the paper forms already had.