fix error in gitignore
This commit is contained in:
@@ -0,0 +1,176 @@
|
||||
"""Seed demo data: roles, users, facilities/schedules/slots, a complete default
|
||||
workflow (with approval + payment + invoice + Odoo-sync steps), pricing rules,
|
||||
notification templates and a report definition.
|
||||
|
||||
The workflow seeded here is demo DATA ONLY — the engine itself remains fully
|
||||
dynamic and knows nothing about pistachio processing.
|
||||
"""
|
||||
from decimal import Decimal
|
||||
|
||||
from django.contrib.auth import get_user_model
|
||||
from django.core.management.base import BaseCommand
|
||||
from django.db import transaction
|
||||
from django.utils import timezone
|
||||
|
||||
from apps.accounts.models import Customer
|
||||
from apps.notifications.models import NotificationTemplate
|
||||
from apps.pricing.models import PricingRule
|
||||
from apps.rbac.models import Permission, Role
|
||||
from apps.reports.models import ReportDefinition, ReportField
|
||||
from apps.reservations.models import Facility, FacilitySchedule
|
||||
from apps.reservations.slot_service import SlotService
|
||||
from apps.workflows.engine import WorkflowEngine
|
||||
from apps.workflows.models import Workflow, WorkflowStep, WorkflowTransition, WorkflowVersion
|
||||
|
||||
User = get_user_model()
|
||||
|
||||
PERMISSIONS = [
|
||||
"reservation.view", "reservation.create", "reservation.update", "reservation.cancel", "reservation.approve",
|
||||
"slot.manage",
|
||||
"weighing.view", "weighing.create", "weighing.update",
|
||||
"workflow.view", "workflow.create", "workflow.update", "workflow.publish",
|
||||
"processing.view", "processing.start", "processing.pause", "processing.complete",
|
||||
"invoice.view", "invoice.create", "invoice.cancel",
|
||||
"report.view", "report.create",
|
||||
"user.view", "user.manage", "role.view", "role.manage",
|
||||
"settings.manage",
|
||||
]
|
||||
|
||||
ROLE_SPECS = {
|
||||
"administrator": ("Administrator", PERMISSIONS),
|
||||
"facility_manager": ("Facility Manager", [
|
||||
"reservation.view", "reservation.update", "reservation.cancel", "reservation.approve", "slot.manage",
|
||||
"weighing.view", "weighing.create", "weighing.update",
|
||||
"processing.view", "processing.start", "processing.complete",
|
||||
"invoice.view", "report.view", "report.create", "user.view",
|
||||
]),
|
||||
"operator": ("Operator", [
|
||||
"reservation.view", "weighing.view", "weighing.create",
|
||||
"processing.view", "processing.start", "processing.pause", "processing.complete",
|
||||
]),
|
||||
"customer": ("Customer", ["reservation.view", "reservation.create", "processing.view", "report.view"]),
|
||||
"accountant": ("Accountant", ["invoice.view", "invoice.create", "invoice.cancel", "report.view"]),
|
||||
"quality_controller": ("Quality Controller", ["processing.view", "processing.complete", "report.create"]),
|
||||
}
|
||||
|
||||
# (key, name, flags)
|
||||
STEP_DEFS = [
|
||||
("reservation", "Reservation", {"is_start": True}),
|
||||
("approval", "Approval", {}),
|
||||
("weighing", "Weighing", {"required": True}),
|
||||
("processing_selection", "Processing Selection", {"required": True}),
|
||||
("customer_confirmation", "Customer Confirmation", {"requires_customer_confirmation": True}),
|
||||
("payment", "Payment", {"requires_payment": True}),
|
||||
("sorting", "Sorting", {}),
|
||||
("washing", "Washing", {}),
|
||||
("drying", "Drying", {}),
|
||||
("quality_control", "Quality Control", {}),
|
||||
("packaging", "Packaging", {}),
|
||||
("final_weighing", "Final Weighing", {}),
|
||||
("final_report", "Final Report", {}),
|
||||
("invoice", "Invoice", {"triggers_invoice": True, "triggers_odoo_sync": True}),
|
||||
("completed", "Completed", {"is_terminal": True}),
|
||||
]
|
||||
|
||||
REPORT_FIELDS = [
|
||||
("final_moisture", "Final Moisture", "decimal"),
|
||||
("quality_grade", "Quality Grade", "choice"),
|
||||
("broken_percentage", "Broken Percentage", "percentage"),
|
||||
("category_a_weight", "Category A Weight", "weight"),
|
||||
("category_b_weight", "Category B Weight", "weight"),
|
||||
("category_c_weight", "Category C Weight", "weight"),
|
||||
]
|
||||
|
||||
|
||||
class Command(BaseCommand):
|
||||
help = "Seed demo roles, users, facilities, a default workflow, pricing, templates and reports."
|
||||
|
||||
@transaction.atomic
|
||||
def handle(self, *args, **options):
|
||||
perms = {}
|
||||
for code in PERMISSIONS:
|
||||
perms[code], _ = Permission.objects.get_or_create(code=code, defaults={"description": code})
|
||||
|
||||
roles = {}
|
||||
for slug, (name, codes) in ROLE_SPECS.items():
|
||||
role, _ = Role.objects.get_or_create(slug=slug, defaults={"name": name})
|
||||
role.permissions.set([perms[c] for c in codes])
|
||||
roles[slug] = role
|
||||
|
||||
def make_user(username, role_slug, **kw):
|
||||
user, _ = User.objects.get_or_create(username=username, defaults=kw)
|
||||
user.set_password("demo1234")
|
||||
user.save()
|
||||
if not user.user_roles.filter(role=roles[role_slug]).exists():
|
||||
user.user_roles.create(role=roles[role_slug])
|
||||
return user
|
||||
|
||||
make_user("admin", "administrator", is_staff=True, is_superuser=True, email="admin@example.com")
|
||||
make_user("manager", "facility_manager")
|
||||
make_user("operator", "operator")
|
||||
make_user("accountant", "accountant")
|
||||
make_user("qc", "quality_controller")
|
||||
cust_user = make_user("customer", "customer", email="customer@example.com", phone="09120000000")
|
||||
Customer.objects.get_or_create(user=cust_user, defaults={"company_name": "Demo Pistachio Co."})
|
||||
|
||||
# Facility + schedule + slots
|
||||
facility, _ = Facility.objects.get_or_create(name="Main Facility")
|
||||
tomorrow = timezone.localdate() + timezone.timedelta(days=1)
|
||||
FacilitySchedule.objects.update_or_create(
|
||||
facility=facility, date=tomorrow, defaults={"is_open": True, "capacity": 3}
|
||||
)
|
||||
SlotService().generate_slots(facility, tomorrow)
|
||||
|
||||
# Default workflow
|
||||
workflow, _ = Workflow.objects.get_or_create(
|
||||
slug="pistachio-processing",
|
||||
defaults={"name": "Pistachio Processing", "description": "Default configurable workflow"},
|
||||
)
|
||||
version = WorkflowVersion.objects.create(workflow=workflow, version=workflow.versions.count() + 1)
|
||||
steps = {}
|
||||
for order, (key, name, flags) in enumerate(STEP_DEFS):
|
||||
steps[key] = WorkflowStep.objects.create(
|
||||
version=version, key=key, name=name, order=order,
|
||||
position_x=80 + (order % 5) * 200, position_y=40 + (order // 5) * 160,
|
||||
**flags,
|
||||
)
|
||||
chain = [d[0] for d in STEP_DEFS]
|
||||
for a, b in zip(chain, chain[1:]):
|
||||
WorkflowTransition.objects.create(version=version, from_step=steps[a], to_step=steps[b])
|
||||
|
||||
# Pricing
|
||||
PricingRule.objects.get_or_create(step=steps["washing"], name="Washing per kg", rule_type="per_kg", amount=Decimal("5000"))
|
||||
PricingRule.objects.get_or_create(step=steps["drying"], name="Drying per kg", rule_type="per_kg", amount=Decimal("8000"))
|
||||
PricingRule.objects.get_or_create(step=steps["sorting"], name="Sorting per kg", rule_type="per_kg", amount=Decimal("12000"))
|
||||
|
||||
# Report definition
|
||||
definition, _ = ReportDefinition.objects.get_or_create(
|
||||
workflow=workflow, name="Default Processing Report", defaults={"active": True}
|
||||
)
|
||||
for order, (key, label, field_type) in enumerate(REPORT_FIELDS):
|
||||
ReportField.objects.get_or_create(
|
||||
definition=definition, key=key,
|
||||
defaults={"label": label, "field_type": field_type, "order": order},
|
||||
)
|
||||
|
||||
# Notification templates
|
||||
NotificationTemplate.objects.get_or_create(
|
||||
event="reservation.approved", channel="sms",
|
||||
defaults={"body": "Cetana: reservation {{reservation_title}} on {{slot_date}} at {{slot_time}} is confirmed."},
|
||||
)
|
||||
NotificationTemplate.objects.get_or_create(
|
||||
event="order.completed", channel="sms",
|
||||
defaults={"body": "Cetana: order {{order_number}} is complete. Final report is ready."},
|
||||
)
|
||||
|
||||
try:
|
||||
WorkflowEngine().publish(workflow, version)
|
||||
except Exception as exc: # pragma: no cover
|
||||
self.stdout.write(self.style.WARNING(f"Workflow publish skipped: {exc}"))
|
||||
|
||||
# Pre-fill the Odoo server URL (credentials are entered in Settings).
|
||||
from apps.core.models import SystemSetting
|
||||
|
||||
SystemSetting.objects.get_or_create(key="odoo.url", defaults={"value": "https://rayayazd.ir"})
|
||||
|
||||
self.stdout.write(self.style.SUCCESS("Seed data created. Logins use password 'demo1234'."))
|
||||
Reference in New Issue
Block a user