updates on the backend about the reverse logistics

This commit is contained in:
2026-10-10 12:40:42 +05:30
parent 153be40e5c
commit d1947dcd7a
6 changed files with 233 additions and 82 deletions

View File

@@ -1,56 +1,76 @@
package constants
import "strings"
// What a client delivers, and what that implies operationally.
//
// ─── One vocabulary, not two ───────────────────────────────────────────────
//
// These eight values already existed as `validCategories` in
// controllers/doormilePricingController.go and as the comment on
// models.DoormilePricing.Category. Tenants now carry one too, so the set is
// promoted here rather than copied: a second list would drift, and a tenant
// whose category is not a pricing category cannot be priced.
// Categories driven by pricing, onboarding, and logistics.
// Non-perishable goods like Steel, Clothing, Electronics, Automotive have return paths.
// Perishable goods like Food, Meat, and Fresh Produce have NO return option.
var DeliveryCategories = map[string]bool{
"General": true,
"Documents": true,
"Electronics": true,
"Clothing": true,
"Fragile": true,
"Medical": true,
"Automotive": true,
"Food": true,
"General": true,
"Documents": true,
"Electronics": true,
"Clothing": true,
"Fragile": true,
"Medical": true,
"Automotive": true,
"Steel": true,
"Food": true,
"Meat": true,
"FreshProduce": true,
}
// DeliveryCategoryList is the same set, ordered, for anything that renders a
// choice. General first because it is the safe default; Food last because it
// is the one that turns a capability off.
// DeliveryCategoryList is the same set, ordered, for anything that renders a choice.
var DeliveryCategoryList = []string{
"General", "Documents", "Electronics", "Clothing",
"Fragile", "Medical", "Automotive", "Food",
"Fragile", "Medical", "Automotive", "Steel", "Food", "Meat", "FreshProduce",
}
// CategoryDefault is what a client with no category recorded is treated as.
// Every tenant onboarded before this field existed has an empty string, and
// they must keep behaving exactly as they did — which means reverse logistics
// stays available to them.
const CategoryDefault = "General"
// ReverseLogisticsAllowed reports whether a return journey makes sense for
// what this client ships.
//
// Food is the exception: a meal that comes back is waste, not inventory. There
// is nothing to restock, nothing to refund against a returned item, and a
// rider carrying it to a hub is carrying rubbish. Offering RTO there is not a
// harmless extra button — it invites an operator to start a return journey
// that can only end in disposal, and it puts a return charge on a client's
// invoice for a parcel nobody can resell.
//
// Everything else can come back: clothing is the canonical case (wrong size),
// and electronics, documents and automotive parts all have a real return path.
//
// An UNKNOWN or empty category allows returns. That is deliberate: this field
// is new, every existing tenant has no value for it, and a default of "off"
// would silently withdraw a working capability from every client already using
// it. New information must not change old behaviour.
func ReverseLogisticsAllowed(category string) bool {
return category != "Food"
// NonReturnableCategories defines categories of goods that cannot be returned
// (Food items, Meat items, Fresh produce/perishables). Returning them causes
// spoilage and health risks. Non-perishables like Steel, Clothing, Electronics, etc. can be returned.
var NonReturnableCategories = map[string]bool{
"food": true,
"meat": true,
"raw meat": true,
"fresh produce": true,
"freshproduce": true,
"fresh": true,
"perishable": true,
"fish": true,
"seafood": true,
"poultry": true,
"dairy": true,
"vegetables": true,
"fruits": true,
}
// IsPerishableCategory checks if a category or item description is perishable (food, meat, fresh produce).
func IsPerishableCategory(category string) bool {
cat := strings.ToLower(strings.TrimSpace(category))
if cat == "" {
return false
}
if NonReturnableCategories[cat] {
return true
}
if strings.Contains(cat, "food") || strings.Contains(cat, "meat") || strings.Contains(cat, "fresh") {
return true
}
return false
}
// ReverseLogisticsAllowed reports whether a return journey makes sense for
// what this client or parcel ships.
//
// Food items, Meat items, and Fresh produce CANNOT be returned.
// Products like Steel, Electronics, Clothing, and Automotive CAN be returned.
func ReverseLogisticsAllowed(category string) bool {
return !IsPerishableCategory(category)
}