Add a screen to set prices per branch

Branch price overrides were already applied at the till, in cash sales
and in M-Pesa, but nothing could set them.

- Products -> Branch prices (/admin/prices): pick a branch and set its
  price for any product; setting it back to the default removes the
  override, and "Use default" resets it. Branch managers see their own
  branch's prices read-only.
- /api/branch-prices: GET (owner: any branch; manager: own), PUT and
  DELETE (owner only). Branch and product must belong to the business;
  prices must be above zero; who changed a price is recorded.
- Branch pricing is a plan feature, as the Growth plan already
  advertised: Growth and Enterprise, plus any business on its free
  trial. A paid Starter business keeps any prices set during its trial
  and can reset them, but cannot set new ones.
- The catalogue view on the Products page always shows default prices;
  the till's view shows what the branch charges.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-12 10:45:37 +03:00
parent 38facd3d9d
commit 0f609d57bb
8 changed files with 545 additions and 5 deletions
+2
View File
@@ -41,6 +41,7 @@ export interface IBranchPricing extends Document {
branchId: Types.ObjectId;
productId: Types.ObjectId;
unitPrice: number;
updatedBy: Types.ObjectId | null;
updatedAt: Date;
}
@@ -50,6 +51,7 @@ const branchPricingSchema = new Schema<IBranchPricing>(
branchId: { type: Schema.Types.ObjectId, ref: "Branch", required: true },
productId: { type: Schema.Types.ObjectId, ref: "Product", required: true },
unitPrice: { type: Number, required: true, min: 0 },
updatedBy: { type: Schema.Types.ObjectId, ref: "User", default: null },
},
{ timestamps: { createdAt: false, updatedAt: true } }
);