Skip to content

Phase 09: Price Revision

Duration: 1.5 days Goal: Implement ongoing price revision workflow per DPR Section 3.2


After initial onboarding (Phase 06), suppliers may request price revisions due to:

  • Raw material cost changes
  • GST/tax rate changes
  • Manufacturing cost increases
  • Market price alignment

This phase implements the Price Revision Committee (PRC) workflow.


class PriceRevisionRequest(BaseDocType):
"""Supplier request for price change on existing item."""
# Identity
request_no: str = Field(max_length=50, unique=True)
# Item
item: str # FK to Item
item_name: str
supplier: str # FK to Supplier
# Current Pricing
current_mrp: Decimal
current_legacy_erp_price: Decimal
current_discount_percent: Decimal
# Proposed Pricing
proposed_mrp: Decimal
proposed_legacy_erp_price: Decimal
proposed_discount_percent: Decimal
# Justification
revision_reason: str # Cost Increase, GST Change, Market Alignment, Other
justification: str # Detailed explanation
effective_date: date
# Supporting Documents
costing_sheet: str | None = None # FK to File
gst_invoice: str | None = None
market_survey: str | None = None
# Workflow
status: str = "Draft" # Draft, Submitted, PRC Review, BoA Pending, Approved, Rejected
docstatus: int = 0
class Meta:
table_name = "price_revision_request"
workflow = "PriceRevisionWorkflow"
indexes = ["item", "supplier", "status"]
  • Create PriceRevisionRequest DocType
  • Supplier portal submission form
  • Auto-calculate discount percent from MRP/Legacy ERP price
  • Document upload for justification

class PRCChart(BaseDocType):
"""Price Revision Committee analysis chart."""
revision_request: str # FK to PriceRevisionRequest
# Item Details
item: str
item_name: str
item_group: str
# Price Comparison
current_mrp: Decimal
proposed_mrp: Decimal
mrp_change_percent: Decimal
current_legacy_erp_price: Decimal
proposed_legacy_erp_price: Decimal
legacy_erp_price_change_percent: Decimal
# Market Analysis
market_survey_price: Decimal | None = None
competitor_1_price: Decimal | None = None
competitor_2_price: Decimal | None = None
# History
last_revision_date: date | None = None
revisions_in_last_year: int = 0
# PRC Meeting
prc_date: date | None = None
prc_members: list[str] = Field(default_factory=list)
mom_document: str | None = None
# Recommendation
recommendation: str = "Pending" # Pending, Approve, Partial Approve, Reject
approved_legacy_erp_price: Decimal | None = None
remarks: str | None = None
class Meta:
table_name = "prc_chart"
  • Create PRCChart DocType
  • Auto-populate from revision request
  • Fetch price history from Item
  • Calculate change percentages
  • MoM upload functionality

PriceRevisionWorkflow = Workflow(
name="PriceRevisionWorkflow",
states=[
State("Draft", is_initial=True),
State("Submitted"),
State("F&A Review"), # Finance & Accounts initial review
State("PRC Review"), # Price Revision Committee
State("BoA Pending"), # For significant changes
State("Approved", is_final=True),
State("Rejected", is_final=True),
],
transitions=[
# Supplier submits
Transition("Submit", "Draft", "Submitted"),
# F&A first review
Transition("Accept for Review", "Submitted", "F&A Review"),
Transition("Reject Incomplete", "Submitted", "Rejected"),
# F&A to PRC
Transition("Send to PRC", "F&A Review", "PRC Review"),
Transition("Reject", "F&A Review", "Rejected"),
# PRC decisions
Transition("Approve", "PRC Review", "Approved"), # Minor changes
Transition("Escalate to BoA", "PRC Review", "BoA Pending"), # Major changes
Transition("Reject", "PRC Review", "Rejected"),
# BoA decisions
Transition("Approve", "BoA Pending", "Approved"),
Transition("Reject", "BoA Pending", "Rejected"),
Transition("Send Back to PRC", "BoA Pending", "PRC Review"),
]
)
  • BoA Required if:
    • Price increase > 10%
    • Discount reduction > 2%
    • More than 2 revisions in 12 months
    • Liquor/AFD category items

class PriceRevisionController(BaseController[PriceRevisionRequest]):
async def on_approve(self, doc: PriceRevisionRequest) -> None:
"""Update Item prices on approval."""
# Get approved price from PRC chart
prc = await self.get_prc_chart(doc.id)
new_price = prc.approved_legacy_erp_price or doc.proposed_legacy_erp_price
# Update Item master
item = await self.item_repo.get(doc.item)
# Archive current price
await self.create_price_history(item)
# Apply new price
item.mrp = doc.proposed_mrp
item.legacy_erp_price = new_price
item.discount_percent = calculate_discount(doc.proposed_mrp, new_price)
item.last_price_revision = date.today()
await self.item_repo.save(item)
# Publish event for cache invalidation
await self.event_bus.publish("item.price_updated", {
"item_id": str(item.id),
"old_price": str(doc.current_legacy_erp_price),
"new_price": str(new_price),
})
# Notify supplier
await self.notify_supplier(doc, "approved")

class ItemPriceHistory(BaseDocType):
"""Historical record of item prices."""
item: str # FK to Item
mrp: Decimal
legacy_erp_price: Decimal
discount_percent: Decimal
effective_from: date
effective_to: date | None = None
# Reference
revision_request: str | None = None # FK if from revision
reason: str | None = None
class Meta:
table_name = "item_price_history"
indexes = ["item", "effective_from"]

Endpoint Method Description
/api/v1/price-revision POST Submit revision request
/api/v1/price-revision/{id}/submit POST Submit for review
/api/v1/prc-chart/{id}/recommend POST PRC recommendation
/api/v1/price-revision/{id}/approve POST Approve revision
/api/v1/items/{id}/price-history GET Get price history

async def pending_revisions_report(filters: dict) -> ReportResult:
"""List all pending price revision requests."""
return await repo.list(
filters=[
FilterSpec("status", FilterOperator.IN, ["Submitted", "F&A Review", "PRC Review", "BoA Pending"]),
],
order_by=[OrderSpec("created", OrderDirection.ASC)],
)
  • Items with multiple revisions in period
  • Average price change by category
  • Supplier-wise revision frequency

Event When
price_revision.submitted Request submitted by supplier
price_revision.approved Request approved
price_revision.rejected Request rejected
item.price_updated Item price changed

  • Supplier can submit revision request
  • F&A can review and forward to PRC
  • PRC chart auto-populates
  • BoA escalation works for major changes
  • Item price updates on approval
  • Price history maintained
  • Supplier notifications at each stage
  • Audit trail complete

Task Duration
DocTypes 0.5 day
Workflow 0.25 day
Controllers 0.25 day
Reports 0.25 day
Tests 0.25 day
Total 1.5 days