Kpc
Kenya Pipeline Company
- Author: Excel-Technologies-Ltd
- Repository: https://github.com/Excel-Technologies-Ltd/KPC
- GitHub stars: 0
- Forks: 0
- License: NOASSERTION
- Category: HR & Payroll
- Maintenance: Actively Maintained
Install Kpc
bench get-app https://github.com/Excel-Technologies-Ltd/KPC
Add the Frappe Gems badge to your README
Maintain Kpc? Paste this into your README:
[](https://frappegems.com/gems/apps/Excel-Technologies-Ltd/KPC)
About Kpc
KPC Operations
An end-to-end Petroleum Operations Platform for Kenya Pipeline Company (KPC) — built on Frappe and integrated with standard ArcApps Accounts and Stock.
It tracks physical petroleum cargo from vessel arrival through to financial posting, across 13 steps, with an integrated AI predictive-maintenance event during pipeline movement. A single Golden Thread ID (journey_ref) is enforced on every transaction in the chain, so any cargo can be traced end to end.
New to the business, not just the code? See BUSINESS_GUIDE.md — it explains the petroleum-operations concepts behind the workflow (standard volume/VCF, interface cuts, reconciliation tolerance, credit/stock checks, ...) and, doctype by doctype, what every field actually means and why the app asks for it. This document (README.md) is the technical/architecture record of what was built; that one is the functional/business explainer.
The Golden Thread
Every transaction doctype in this app carries a mandatory journey_ref — a Link to a Journey record, not a free-text string. Journey is the golden-thread master: it's created automatically the moment an Oil Shipment is first saved, and every subsequent step appends an audit row to its journey_log child table via one shared helper:
from kpc.petroleum_operations.utils import log_journey_step
log_journey_step(self.journey_ref, "7. Movement", self)
A Journey is read-only and system-maintained — nobody edits it by hand. Open any Journey record to see the complete, ordered history of every document raised against that cargo, from the originating Oil Shipment all the way to the Financial Posting that closed it out.
The 13-Step Workflow
| # | Step | DocType(s) |
|---|---|---|
| 1 | Shipment | Oil Shipment |
| 2 | Receipt | Tank Measurement |
| 3 | Quality Result | Quality Result |
| 4 | Inventory Position | Inventory Position |
| 5 | Nomination | Nomination |
| 6 | Batch | Pipeline Batch |
| 7 | Movement (+ AI) | Movement, OT Telemetry Log, AI Alert, AI Prediction, AI Recommendation, Maintenance Work Order |
| 8 | Terminal Receipt | Terminal Receipt (creates a real ArcApps Material Transfer Stock Entry) |
| 9 | Reconciliation | Reconciliation, Variance (a recognised loss creates a Material Issue Stock Entry) |
| 10 | Allocation | Allocation |
| 11 | Dispatch | Dispatch (creates a real ArcApps Delivery Note) |
| 12 | Invoice | Invoice (creates a real ArcApps Sales Invoice, billed against the Dispatch's Delivery Note) |
| 13 | Financial Posting | Financial Posting (system-generated, mirrors the Sales Invoice's GL posting) |
Supporting masters that aren't part of the numbered sequence: Terminal, Oil Tank (each auto-provisions a matching ArcApps Warehouse), Capacity Assessment, Tariff, Product Compatibility, Plant Asset, Employee Certification (see Phase 5 below), plus Product, which is not a separate doctype — it's the standard ArcApps Item extended with petroleum-specific custom fields (density_at_15c, reference_temperature_c, api_gravity, is_petroleum_product).
Walking through the workflow, step by step
Written for someone using the app, not just reading its code: what to create, in what order, who normally does it, and what has to be true already before the system will let you move on. Every step below shares one journey_ref — the Golden Thread ID that first appears at Step 1 and rides along, unchangeable, all the way to Step 13. For why each field exists — the underlying petroleum-operations business concepts (standard volume, interface cuts, reconciliation tolerance, and so on) — see BUSINESS_GUIDE.md, which walks the same 13 steps at the field level.
- Shipment — create an
Oil Shipment. The starting point: a Terminal Operator records a vessel (name, product, nominated quantity) the moment it's expected or arrives. Saving it silently creates theJourneybehind the scenes — you don't create that yourself. The Shipment then moves through its own mini-workflow as the vessel physically progresses: Draft → Vessel Arrived → Discharging → Received, each transition timestamped automatically. Nothing downstream can start until a Shipment exists. - Receipt — create a
Tank Measurement. Once product is flowing into a tank, a Terminal Operator takes a dip reading (level, temperature, density) and records it here, tagged to the same tank and Shipment. A Closing reading is the one that counts as "received" — it calculates a standard volume at 15°C and, behind the scenes, posts a real stock receipt into that tank's warehouse. You can't measure into a tank that's under Maintenance or Quarantine. - Quality Result — create a
Quality Result. A lab technician (Quality Analyst) enters the sample's parameters (density, sulphur, etc.) against spec. The record starts Pending; a different person with the Quality Manager role then reviews it and decides Accepted or Quarantined — the same person can't do both steps for the same result. A Quarantined result locks the sampled tank. Nothing can be nominated for sale (Step 5) until its Quality Result is Accepted. - Inventory Position — create an
Inventory Position. A running snapshot of how much of a product is sitting in a tank right now (opening + receipts − dispatches). The first one, right after Receipt, is created the same way as everything else here — a person records the origin tank's opening position off the Tank Measurement's volume. After that, later positions (at Terminal Receipt and Dispatch) are appended automatically by the system as stock actually moves, each one carrying forward the previous closing balance as its own opening — you only create this one by hand. - Nomination — create a
Nomination. A Commercial Officer records a customer's order against a specific, quality-released parcel. Submitting it ("accepting" the order) automatically checks the customer's credit limit and that there's genuinely enough stock on hand for that journey — either check failing blocks the submit outright, no manual override. - Batch — create a
Pipeline Batch(optionally after aCapacity Assessmentfor that route/period). A Scheduler turns an accepted Nomination into a scheduled pumping slot, giving it a position in the pumping sequence (Pumping Sequence No). The system checks the batch doesn't over-commit the Nomination's quantity or the route's pipeline capacity, and — importantly — checks the Product Compatibility matrix against whichever batch is scheduled immediately before/after it on the same route: an outright incompatible pairing is blocked, and a pairing that merely needs an interface cut won't submit until you've entered a large-enough cut volume. - Movement (+ AI) — create a
Movement. The actual pumping run. A Scheduler/Terminal Operator tracks its status (Draft → In Transit → Completed/Halted) and either types in telemetry readings directly or, more realistically, lets pressure/flow/vibration arrive automatically viaOT Telemetry Log(a read-only ingest point — see the OT Safety Boundary above). A reading outside the safe envelope automatically raises anAI Alert→AI Prediction→ a draftAI Recommendation. Nothing happens to equipment on its own: a human with the Maintenance Manager role has to explicitly Approve (or Reject) the recommendation before aMaintenance Work Ordercan be raised from it — and that approval is written permanently to the Decision Ledger. A hazardous repair job additionally needs aPermit to Workissued to a specific Employee holding the right, current certification before it can proceed. - Terminal Receipt — create a
Terminal Receipt. The pipeline movement's arrival: another dip reading, this time at the destination tank, which posts a real stock transfer from the origin tank's warehouse to the destination's. - Reconciliation — create a
Reconciliation. Compares what was dispatched against what actually arrived. The acceptable variance (tolerance) isn't a policy number you set — it's calculated automatically from the measurement uncertainty of the two dip readings that bracket the journey. If the variance is outside that tolerance, submitting is blocked until you provide a written justification; doing so is itself logged to the Decision Ledger as an override, not silently allowed. Any recognised physical loss is then followed up with aVariancerecord — created separately, classifying the loss (e.g. evaporation, measurement tolerance, theft) — which a second person has to Approve or Reject before it's considered resolved. - Allocation — create an
Allocation. Once Reconciliation confirms what actually arrived, a Commercial Officer assigns (allocates) that confirmed volume to a specific Nomination/customer — this is the moment KPC-custody stock becomes customer-owned stock, on paper. - Dispatch — create a
Dispatch. The delivery itself. Submitting it creates and submits a real ArcApps Delivery Note in the same step — this is the delivery chalan a driver takes with the load; there's no separate manual step to raise one. - Invoice — create an
Invoice. A Commercial or Finance Officer adds one line per Dispatch, each priced against an activeTariff, and submits. This creates and submits a real ArcApps Sales Invoice, billed against the Dispatch's own Delivery Note quantity — you can't invoice more than was actually delivered. - Financial Posting — nothing to create. The system raises this automatically the moment the Invoice is submitted, mirroring the Sales Invoice's own GL posting so the Golden Thread has a record of it. If the Invoice is ever cancelled, this flips to Reversed automatically too.
The short version of "what do I create first": Shipment → Tank Measurement → Quality Result → Inventory Position → Nomination → Pipeline Batch → Movement → Terminal Receipt → Reconciliation (+ Variance) → Allocation → Dispatch → Invoice → (Financial Posting happens automatically). Every arrow is enforced by the system, not just convention — you genuinely cannot create most of these out of order; the ones you'd try first will simply refuse to submit and tell you what's missing.
Phase 1 Hardening: write-once journey_ref, Product Compatibility, RBAC
A follow-up pass over Steps 1–4 (Inbound Logistics & Storage) toward a larger, security-and-safety-focused spec. Everything below is implemented and verified against live demo data on this codebase; later phases of that spec (OT ingest boundary, combined measurement uncertainty, EAM/HSEQ, AI Decision Ledger, and the global "owner cannot approve their own document" SoD hook) are not yet started and will land in dedicated follow-up passes.
journey_refis write-once, not just read-only in the UI.kpc.petroleum_operations.utils.assert_journey_ref_immutable(doc)compares the incoming value against the DB value on everyvalidate()and throws if they differ, on any document that isn't new — closing the gap whereread_onlyalone only stops the desk form, notfrappe.get_doc(...).save(ignore_permissions=True)from a script or API call. Wired intoOil Shipment,Tank Measurement,Quality Result, andInventory Position. (On an already-submitted document, Frappe's ownUpdateAfterSubmitErrortypically fires first sincejourney_refisn'tallow_on_submit— the custom guard is what actually stops a change on a still-draft document, which submit-immutability doesn't cover.)Product Compatibility— a new master doctype recording pipeline batch-adjacency rules between two Products (Items):Compatible(default, open-world — an unlisted pair is assumed compatible),Requires Interface Cut(with a mandatoryminimum_interface_cut_kl), or `
Related HR & Payroll apps for Frappe & ERPNext
- Hrms — Open Source HR and Payroll Software
- Huf — Open-source, self-hosted multi-agent AI infrastructure for teams and apps with support for cloud and local models, tool integrations, workflows, and automation across business systems including Slack, ERPNext, Discord & Gmail.
- Bookings — Hotel Management App for Erpnext
- Employee Self Service — This is the backend component for Nesscale ESS - a mobile app that brings ERPNext to your phone. Employees can manage their HR tasks, sales activities, and projects right from their mobile devices.
- Inventory Tools — A collection of features to streamline and enhance inventory management and manufacturing workflows in ERPNext.
- Check Run — Payables utility for ERPNext
- Next Ai — NextAI is an AI-powered app for Frappe and ERPNext, delivering seamless content generation, automation, and productivity enhancements.
- Projectit — Open Source PWA mobile app to track the Employees out in the field. This mobile app is developed on Frappe Framework and it is integrated with the Project functionalities of ERPNext and integrated tightly with Frappe HR.