feat: accounting added

This commit is contained in:
2026-08-02 19:37:22 +03:30
parent cce279a60d
commit dd5b6d4616
10 changed files with 945 additions and 51 deletions
+30
View File
@@ -1,10 +1,40 @@
import { User } from "@/types/user";
import { Purchase } from "@/types/purchase";
// Single source of truth for product type labels lives in types/product.ts
// (kept in sync with the backend Product::TYPES). Re-exported here so existing
// `@/lib/utils` imports keep working without a divergent (previously wrong) map.
export { getProductTypeLabel } from "@/types/product";
// قیمت نهایی خرید — shared between purchases table and accounting page.
// اگر محصول تخفیف داشته باشد قیمت تخفیف‌خورده، در غیر این صورت قیمت اصلی، و در نهایت مبلغ تراکنش.
export const getPurchaseFinalPrice = (purchase: Purchase): number => {
const product = purchase.product;
// اگر محصول تخفیف دارد، قیمت نهایی همان قیمت تخفیف‌خورده است
const discountedPrice = product?.discounted_price;
if (discountedPrice) {
const parsed = parseInt(discountedPrice.replace(/[^\d]/g, ''), 10);
if (!Number.isNaN(parsed) && parsed > 0) return parsed;
}
// بدون تخفیف → قیمت اصلی محصول
if (product?.price) return product.price;
// برگشت به مبلغ ثبت‌شدهٔ تراکنش وقتی محصول در دسترس نیست
return purchase.amount || 0;
};
// Parse a percentage input (e.g. "۱۵%" / "15") and clamp to 0100.
export const parseStoreRate = (value: string | number): number => {
if (value === null || value === undefined || value === '') return 0;
const str = String(value).replace(/[^\d]/g, '');
if (!str) return 0;
const n = parseInt(str, 10);
if (Number.isNaN(n)) return 0;
return Math.min(100, Math.max(0, n));
};
export const formatDate = (dateString: string | null): string => {
if (!dateString) return 'نامشخص';