Deploy via committed dist: local Nest build, server runs with .env

Build on the developer machine without Docker, commit dist/, and run on the server with Dockerfile.dist plus compose env_file.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-08-05 21:35:22 +03:30
co-authored by Cursor
parent 67cfc17079
commit cbcea58e94
199 changed files with 10895 additions and 4 deletions
+4
View File
@@ -0,0 +1,4 @@
export declare function computeCashInvoiceExpiry(company: {
cashInvoiceValidUntilHour: number | null;
cashInvoiceValidityHours: number;
}): Date;
+17
View File
@@ -0,0 +1,17 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.computeCashInvoiceExpiry = computeCashInvoiceExpiry;
function computeCashInvoiceExpiry(company) {
const now = new Date();
if (company.cashInvoiceValidUntilHour != null &&
Number.isFinite(company.cashInvoiceValidUntilHour)) {
const expires = new Date(now);
expires.setHours(company.cashInvoiceValidUntilHour, 0, 0, 0);
if (expires.getTime() <= now.getTime()) {
expires.setDate(expires.getDate() + 1);
}
return expires;
}
return new Date(now.getTime() + company.cashInvoiceValidityHours * 60 * 60 * 1000);
}
//# sourceMappingURL=cash-expiry.js.map
+1
View File
@@ -0,0 +1 @@
{"version":3,"file":"cash-expiry.js","sourceRoot":"","sources":["../../../src/common/utils/cash-expiry.ts"],"names":[],"mappings":";;AAAA,4DAoBC;AApBD,SAAgB,wBAAwB,CAAC,OAGxC;IACC,MAAM,GAAG,GAAG,IAAI,IAAI,EAAE,CAAC;IACvB,IACE,OAAO,CAAC,yBAAyB,IAAI,IAAI;QACzC,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,yBAAyB,CAAC,EAClD,CAAC;QACD,MAAM,OAAO,GAAG,IAAI,IAAI,CAAC,GAAG,CAAC,CAAC;QAC9B,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAC,yBAAyB,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;QAC7D,IAAI,OAAO,CAAC,OAAO,EAAE,IAAI,GAAG,CAAC,OAAO,EAAE,EAAE,CAAC;YACvC,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC,CAAC;QACzC,CAAC;QACD,OAAO,OAAO,CAAC;IACjB,CAAC;IAED,OAAO,IAAI,IAAI,CACb,GAAG,CAAC,OAAO,EAAE,GAAG,OAAO,CAAC,wBAAwB,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAClE,CAAC;AACJ,CAAC"}
+13
View File
@@ -0,0 +1,13 @@
export type CheckRassInput = {
amount: number;
dueDate: Date | string;
};
export type CheckRassResult = {
checkCount: number;
totalAmount: number;
nearestDueDate: string | null;
farthestDueDate: string | null;
rassDays: number;
rassDate: string | null;
};
export declare function calculateCheckRass(checks: CheckRassInput[], baseDate?: Date): CheckRassResult;
+44
View File
@@ -0,0 +1,44 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.calculateCheckRass = calculateCheckRass;
function startOfDay(date) {
const d = new Date(date);
d.setHours(0, 0, 0, 0);
return d;
}
function calculateCheckRass(checks, baseDate = new Date()) {
if (checks.length === 0) {
return {
checkCount: 0,
totalAmount: 0,
nearestDueDate: null,
farthestDueDate: null,
rassDays: 0,
rassDate: null,
};
}
const base = startOfDay(baseDate);
let totalAmount = 0;
let weightedDays = 0;
const dueDates = [];
for (const check of checks) {
const due = startOfDay(new Date(check.dueDate));
dueDates.push(due);
const days = Math.max(0, Math.round((due.getTime() - base.getTime()) / (1000 * 60 * 60 * 24)));
totalAmount += check.amount;
weightedDays += check.amount * days;
}
const rassDays = totalAmount > 0 ? Math.round(weightedDays / totalAmount) : 0;
const rassDate = new Date(base);
rassDate.setDate(rassDate.getDate() + rassDays);
dueDates.sort((a, b) => a.getTime() - b.getTime());
return {
checkCount: checks.length,
totalAmount,
nearestDueDate: dueDates[0]?.toISOString() ?? null,
farthestDueDate: dueDates[dueDates.length - 1]?.toISOString() ?? null,
rassDays,
rassDate: rassDate.toISOString(),
};
}
//# sourceMappingURL=check-rass.js.map
+1
View File
@@ -0,0 +1 @@
{"version":3,"file":"check-rass.js","sourceRoot":"","sources":["../../../src/common/utils/check-rass.ts"],"names":[],"mappings":";;AAoBA,gDA4CC;AAlDD,SAAS,UAAU,CAAC,IAAU;IAC5B,MAAM,CAAC,GAAG,IAAI,IAAI,CAAC,IAAI,CAAC,CAAC;IACzB,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;IACvB,OAAO,CAAC,CAAC;AACX,CAAC;AAED,SAAgB,kBAAkB,CAChC,MAAwB,EACxB,WAAiB,IAAI,IAAI,EAAE;IAE3B,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACxB,OAAO;YACL,UAAU,EAAE,CAAC;YACb,WAAW,EAAE,CAAC;YACd,cAAc,EAAE,IAAI;YACpB,eAAe,EAAE,IAAI;YACrB,QAAQ,EAAE,CAAC;YACX,QAAQ,EAAE,IAAI;SACf,CAAC;IACJ,CAAC;IAED,MAAM,IAAI,GAAG,UAAU,CAAC,QAAQ,CAAC,CAAC;IAClC,IAAI,WAAW,GAAG,CAAC,CAAC;IACpB,IAAI,YAAY,GAAG,CAAC,CAAC;IACrB,MAAM,QAAQ,GAAW,EAAE,CAAC;IAE5B,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;QAC3B,MAAM,GAAG,GAAG,UAAU,CAAC,IAAI,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC;QAChD,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QACnB,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,CACnB,CAAC,EACD,IAAI,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,OAAO,EAAE,GAAG,IAAI,CAAC,OAAO,EAAE,CAAC,GAAG,CAAC,IAAI,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC,CAAC,CACrE,CAAC;QACF,WAAW,IAAI,KAAK,CAAC,MAAM,CAAC;QAC5B,YAAY,IAAI,KAAK,CAAC,MAAM,GAAG,IAAI,CAAC;IACtC,CAAC;IAED,MAAM,QAAQ,GAAG,WAAW,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,YAAY,GAAG,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAC9E,MAAM,QAAQ,GAAG,IAAI,IAAI,CAAC,IAAI,CAAC,CAAC;IAChC,QAAQ,CAAC,OAAO,CAAC,QAAQ,CAAC,OAAO,EAAE,GAAG,QAAQ,CAAC,CAAC;IAChD,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC;IAEnD,OAAO;QACL,UAAU,EAAE,MAAM,CAAC,MAAM;QACzB,WAAW;QACX,cAAc,EAAE,QAAQ,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,IAAI,IAAI;QAClD,eAAe,EAAE,QAAQ,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC,EAAE,WAAW,EAAE,IAAI,IAAI;QACrE,QAAQ;QACR,QAAQ,EAAE,QAAQ,CAAC,WAAW,EAAE;KACjC,CAAC;AACJ,CAAC"}
+5
View File
@@ -0,0 +1,5 @@
export declare function splitFullName(name: string): {
firstName: string;
lastName: string;
};
export declare function joinFullName(firstName: string, lastName: string): string;
+22
View File
@@ -0,0 +1,22 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.splitFullName = splitFullName;
exports.joinFullName = joinFullName;
function splitFullName(name) {
const trimmed = name.trim().replace(/\s+/g, ' ');
if (!trimmed) {
return { firstName: 'مشتری', lastName: 'جدید' };
}
const parts = trimmed.split(' ');
if (parts.length === 1) {
return { firstName: parts[0], lastName: '' };
}
return {
firstName: parts[0],
lastName: parts.slice(1).join(' '),
};
}
function joinFullName(firstName, lastName) {
return `${firstName} ${lastName}`.trim();
}
//# sourceMappingURL=name.js.map
+1
View File
@@ -0,0 +1 @@
{"version":3,"file":"name.js","sourceRoot":"","sources":["../../../src/common/utils/name.ts"],"names":[],"mappings":";;AAAA,sCAgBC;AAED,oCAEC;AApBD,SAAgB,aAAa,CAAC,IAAY;IAIxC,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IACjD,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,OAAO,EAAE,SAAS,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,CAAC;IAClD,CAAC;IACD,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IACjC,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACvB,OAAO,EAAE,SAAS,EAAE,KAAK,CAAC,CAAC,CAAE,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAC;IAChD,CAAC;IACD,OAAO;QACL,SAAS,EAAE,KAAK,CAAC,CAAC,CAAE;QACpB,QAAQ,EAAE,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC;KACnC,CAAC;AACJ,CAAC;AAED,SAAgB,YAAY,CAAC,SAAiB,EAAE,QAAgB;IAC9D,OAAO,GAAG,SAAS,IAAI,QAAQ,EAAE,CAAC,IAAI,EAAE,CAAC;AAC3C,CAAC"}
+1
View File
@@ -0,0 +1 @@
export declare function generateOrderNumber(date?: Date): string;
+12
View File
@@ -0,0 +1,12 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.generateOrderNumber = generateOrderNumber;
function generateOrderNumber(date = new Date()) {
const year = new Intl.DateTimeFormat('fa-IR-u-ca-persian', {
year: 'numeric',
}).format(date);
const persianYear = year.replace(/[^\d]/g, '') || '1403';
const seq = Math.floor(Math.random() * 9000) + 1000;
return `ORD-${persianYear}-${seq}`;
}
//# sourceMappingURL=order-number.js.map
+1
View File
@@ -0,0 +1 @@
{"version":3,"file":"order-number.js","sourceRoot":"","sources":["../../../src/common/utils/order-number.ts"],"names":[],"mappings":";;AAAA,kDAOC;AAPD,SAAgB,mBAAmB,CAAC,OAAa,IAAI,IAAI,EAAE;IACzD,MAAM,IAAI,GAAG,IAAI,IAAI,CAAC,cAAc,CAAC,oBAAoB,EAAE;QACzD,IAAI,EAAE,SAAS;KAChB,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;IAChB,MAAM,WAAW,GAAG,IAAI,CAAC,OAAO,CAAC,QAAQ,EAAE,EAAE,CAAC,IAAI,MAAM,CAAC;IACzD,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,IAAI,CAAC,GAAG,IAAI,CAAC;IACpD,OAAO,OAAO,WAAW,IAAI,GAAG,EAAE,CAAC;AACrC,CAAC"}
+5
View File
@@ -0,0 +1,5 @@
import { OrderStatus } from '@prisma/client';
export declare const ADMIN_STATUS_MAP: Record<string, OrderStatus[]>;
export declare function resolveAdminStatusFilter(status?: string): OrderStatus[] | undefined;
export declare function toAdminStatus(status: OrderStatus): string;
export declare const ORDER_STATUS_LABELS: Record<OrderStatus, string>;
+65
View File
@@ -0,0 +1,65 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.ORDER_STATUS_LABELS = exports.ADMIN_STATUS_MAP = void 0;
exports.resolveAdminStatusFilter = resolveAdminStatusFilter;
exports.toAdminStatus = toAdminStatus;
const client_1 = require("@prisma/client");
exports.ADMIN_STATUS_MAP = {
pending_review: [client_1.OrderStatus.awaiting_review, client_1.OrderStatus.pricing],
pending_check: [client_1.OrderStatus.awaiting_check_review],
needs_correction: [client_1.OrderStatus.needs_correction],
check_correction: [client_1.OrderStatus.check_needs_fix],
final_approval: [
client_1.OrderStatus.final_approved,
client_1.OrderStatus.checks_approved,
client_1.OrderStatus.cash_confirmed,
],
shipped: [client_1.OrderStatus.shipped],
delivered: [client_1.OrderStatus.delivered],
};
function resolveAdminStatusFilter(status) {
if (!status)
return undefined;
if (exports.ADMIN_STATUS_MAP[status])
return exports.ADMIN_STATUS_MAP[status];
if (Object.values(client_1.OrderStatus).includes(status)) {
return [status];
}
return undefined;
}
function toAdminStatus(status) {
for (const [admin, list] of Object.entries(exports.ADMIN_STATUS_MAP)) {
if (list.includes(status))
return admin;
}
return status;
}
exports.ORDER_STATUS_LABELS = {
cart: 'سبد خرید',
awaiting_settlement: 'در انتظار تسویه',
cash_in_progress: 'در حال ثبت نقدی',
check_in_progress: 'در حال ثبت چک',
submitted: 'ثبت‌شده',
awaiting_review: 'در انتظار بررسی',
pricing: 'قیمت‌گذاری',
needs_correction: 'نیاز به اصلاح',
awaiting_settlement_fix: 'اصلاح تسویه',
cash_invoice_issued: 'صدور فاکتور نقدی',
awaiting_cash_payment: 'در انتظار پرداخت نقدی',
cash_payment_submitted: 'رسید نقدی ارسال‌شده',
awaiting_cash_confirmation: 'تأیید پرداخت نقدی',
cash_confirmed: 'پرداخت نقدی تأیید شد',
awaiting_check_review: 'بررسی چک',
check_needs_fix: 'اصلاح چک',
check_rejected: 'رد چک',
checks_approved: 'تأیید چک‌ها',
final_approved: 'تأیید نهایی',
preparing: 'آماده‌سازی',
ready_to_ship: 'آماده ارسال',
shipped: 'ارسال‌شده',
delivered: 'تحویل‌شده',
cancelled: 'لغو شده',
rejected: 'رد شده',
expired: 'منقضی',
};
//# sourceMappingURL=order-status.js.map
+1
View File
@@ -0,0 +1 @@
{"version":3,"file":"order-status.js","sourceRoot":"","sources":["../../../src/common/utils/order-status.ts"],"names":[],"mappings":";;;AAiBA,4DASC;AAED,sCAKC;AAjCD,2CAA6C;AAGhC,QAAA,gBAAgB,GAAkC;IAC7D,cAAc,EAAE,CAAC,oBAAW,CAAC,eAAe,EAAE,oBAAW,CAAC,OAAO,CAAC;IAClE,aAAa,EAAE,CAAC,oBAAW,CAAC,qBAAqB,CAAC;IAClD,gBAAgB,EAAE,CAAC,oBAAW,CAAC,gBAAgB,CAAC;IAChD,gBAAgB,EAAE,CAAC,oBAAW,CAAC,eAAe,CAAC;IAC/C,cAAc,EAAE;QACd,oBAAW,CAAC,cAAc;QAC1B,oBAAW,CAAC,eAAe;QAC3B,oBAAW,CAAC,cAAc;KAC3B;IACD,OAAO,EAAE,CAAC,oBAAW,CAAC,OAAO,CAAC;IAC9B,SAAS,EAAE,CAAC,oBAAW,CAAC,SAAS,CAAC;CACnC,CAAC;AAEF,SAAgB,wBAAwB,CACtC,MAAe;IAEf,IAAI,CAAC,MAAM;QAAE,OAAO,SAAS,CAAC;IAC9B,IAAI,wBAAgB,CAAC,MAAM,CAAC;QAAE,OAAO,wBAAgB,CAAC,MAAM,CAAC,CAAC;IAC9D,IAAI,MAAM,CAAC,MAAM,CAAC,oBAAW,CAAC,CAAC,QAAQ,CAAC,MAAqB,CAAC,EAAE,CAAC;QAC/D,OAAO,CAAC,MAAqB,CAAC,CAAC;IACjC,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,SAAgB,aAAa,CAAC,MAAmB;IAC/C,KAAK,MAAM,CAAC,KAAK,EAAE,IAAI,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,wBAAgB,CAAC,EAAE,CAAC;QAC7D,IAAI,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC;YAAE,OAAO,KAAK,CAAC;IAC1C,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC;AAEY,QAAA,mBAAmB,GAAgC;IAC9D,IAAI,EAAE,UAAU;IAChB,mBAAmB,EAAE,iBAAiB;IACtC,gBAAgB,EAAE,iBAAiB;IACnC,iBAAiB,EAAE,eAAe;IAClC,SAAS,EAAE,SAAS;IACpB,eAAe,EAAE,iBAAiB;IAClC,OAAO,EAAE,YAAY;IACrB,gBAAgB,EAAE,eAAe;IACjC,uBAAuB,EAAE,aAAa;IACtC,mBAAmB,EAAE,kBAAkB;IACvC,qBAAqB,EAAE,uBAAuB;IAC9C,sBAAsB,EAAE,qBAAqB;IAC7C,0BAA0B,EAAE,mBAAmB;IAC/C,cAAc,EAAE,sBAAsB;IACtC,qBAAqB,EAAE,UAAU;IACjC,eAAe,EAAE,UAAU;IAC3B,cAAc,EAAE,OAAO;IACvB,eAAe,EAAE,aAAa;IAC9B,cAAc,EAAE,aAAa;IAC7B,SAAS,EAAE,YAAY;IACvB,aAAa,EAAE,aAAa;IAC5B,OAAO,EAAE,WAAW;IACpB,SAAS,EAAE,WAAW;IACtB,SAAS,EAAE,SAAS;IACpB,QAAQ,EAAE,QAAQ;IAClB,OAAO,EAAE,OAAO;CACjB,CAAC"}
+3
View File
@@ -0,0 +1,3 @@
export declare function normalizePhone(raw: string): string;
export declare function isValidPhone(phone: string): boolean;
export declare function toEnglishDigits(value: string): string;
+24
View File
@@ -0,0 +1,24 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.normalizePhone = normalizePhone;
exports.isValidPhone = isValidPhone;
exports.toEnglishDigits = toEnglishDigits;
function normalizePhone(raw) {
let digits = raw.replace(/\D/g, '');
if (digits.startsWith('98') && digits.length === 12) {
digits = `0${digits.slice(2)}`;
}
if (digits.length === 10 && digits.startsWith('9')) {
digits = `0${digits}`;
}
return digits;
}
function isValidPhone(phone) {
return /^09\d{9}$/.test(phone);
}
function toEnglishDigits(value) {
return value
.replace(/[۰-۹]/g, (d) => String('۰۱۲۳۴۵۶۷۸۹'.indexOf(d)))
.replace(/[٠-٩]/g, (d) => String('٠١٢٣٤٥٦٧٨٩'.indexOf(d)));
}
//# sourceMappingURL=phone.js.map
+1
View File
@@ -0,0 +1 @@
{"version":3,"file":"phone.js","sourceRoot":"","sources":["../../../src/common/utils/phone.ts"],"names":[],"mappings":";;AAAA,wCASC;AAED,oCAEC;AAED,0CAIC;AAnBD,SAAgB,cAAc,CAAC,GAAW;IACxC,IAAI,MAAM,GAAG,GAAG,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;IACpC,IAAI,MAAM,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,MAAM,CAAC,MAAM,KAAK,EAAE,EAAE,CAAC;QACpD,MAAM,GAAG,IAAI,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC;IACjC,CAAC;IACD,IAAI,MAAM,CAAC,MAAM,KAAK,EAAE,IAAI,MAAM,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;QACnD,MAAM,GAAG,IAAI,MAAM,EAAE,CAAC;IACxB,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,SAAgB,YAAY,CAAC,KAAa;IACxC,OAAO,WAAW,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;AACjC,CAAC;AAED,SAAgB,eAAe,CAAC,KAAa;IAC3C,OAAO,KAAK;SACT,OAAO,CAAC,QAAQ,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,MAAM,CAAC,YAAY,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC;SACzD,OAAO,CAAC,QAAQ,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,MAAM,CAAC,YAAY,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AAC/D,CAAC"}