Phase 09: Price Revision
Duration: 1.5 days Goal: Implement ongoing price revision workflow per DPR Section 3.2
Overview
Section titled “Overview”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.
1. Price Revision Request DocType
Section titled “1. Price Revision Request DocType”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"]1.1 Tasks
Section titled “1.1 Tasks”- Create
PriceRevisionRequestDocType - Supplier portal submission form
- Auto-calculate discount percent from MRP/Legacy ERP price
- Document upload for justification
2. PRC Chart (Price Revision Committee)
Section titled “2. PRC Chart (Price Revision Committee)”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"2.1 Tasks
Section titled “2.1 Tasks”- Create
PRCChartDocType - Auto-populate from revision request
- Fetch price history from Item
- Calculate change percentages
- MoM upload functionality
3. Workflow Definition
Section titled “3. Workflow Definition”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"), ])Escalation Rules
Section titled “Escalation Rules”- BoA Required if:
- Price increase > 10%
- Discount reduction > 2%
- More than 2 revisions in 12 months
- Liquor/AFD category items
4. Price Update on Approval
Section titled “4. Price Update on Approval”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")5. Price History DocType
Section titled “5. Price History DocType”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"]6. API Endpoints
Section titled “6. API Endpoints”| 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 |
7. Reports
Section titled “7. Reports”7.1 Pending Revisions Report
Section titled “7.1 Pending Revisions Report”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)], )7.2 Price Change Analysis
Section titled “7.2 Price Change Analysis”- Items with multiple revisions in period
- Average price change by category
- Supplier-wise revision frequency
8. Events Published
Section titled “8. Events Published”| 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 |
9. Verification Checklist
Section titled “9. Verification Checklist”- 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
10. Time Estimate
Section titled “10. Time Estimate”| 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 |