tango-api-schema 2.6.31 → 2.6.33
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/index.js +266 -266
- package/package.json +1 -1
- package/schema/bankTransaction.model.js +94 -94
- package/schema/basePricing.model.js +5 -0
- package/schema/billing.model.js +135 -135
- package/schema/estimate.model.js +86 -86
- package/schema/fixtureConfig.model.js +5 -0
- package/schema/fixtureShelf.model.js +5 -0
- package/schema/paymentAccount.model.js +60 -60
- package/schema/paymentReminder.model.js +46 -46
- package/schema/planoCompliance.model.js +5 -0
- package/schema/planoGlobalComment.model.js +4 -0
- package/schema/planoMapping.model.js +5 -0
- package/schema/planoRevision.model.js +8 -0
- package/schema/planoStaticData.model.js +7 -1
- package/schema/planoTaskCompliance.model.js +10 -0
- package/schema/planoVmDetail.model.js +5 -0
- package/schema/planogram.model.js +5 -0
- package/schema/regionKey.model.js +31 -31
- package/schema/storeFixture.model.js +8 -1
- package/schema/storeLayout.model.js +7 -0
- package/schema/taskProcessed.model.js +14 -1
- package/schema/transaction.model.js +54 -54
|
@@ -1,95 +1,95 @@
|
|
|
1
|
-
import mongoose from 'mongoose';
|
|
2
|
-
|
|
3
|
-
// Bank-statement transactions uploaded from the billing "Transactions" tab.
|
|
4
|
-
// Separate from the existing `transaction` collection, which holds payment /
|
|
5
|
-
// wallet (Razorpay) entries. Each row is one statement line; `status` drives
|
|
6
|
-
// the reconciliation buckets shown in the UI.
|
|
7
|
-
const bankTransactionSchema = new mongoose.Schema(
|
|
8
|
-
{
|
|
9
|
-
date: {
|
|
10
|
-
type: Date
|
|
11
|
-
},
|
|
12
|
-
valueDate: {
|
|
13
|
-
type: Date
|
|
14
|
-
},
|
|
15
|
-
narration: {
|
|
16
|
-
type: String
|
|
17
|
-
},
|
|
18
|
-
refNo: {
|
|
19
|
-
type: String,
|
|
20
|
-
index: true
|
|
21
|
-
},
|
|
22
|
-
withdrawalAmt: {
|
|
23
|
-
type: Number,
|
|
24
|
-
default: 0
|
|
25
|
-
},
|
|
26
|
-
depositAmt: {
|
|
27
|
-
type: Number,
|
|
28
|
-
default: 0
|
|
29
|
-
},
|
|
30
|
-
// Signed convenience amount: deposit - withdrawal.
|
|
31
|
-
amount: {
|
|
32
|
-
type: Number
|
|
33
|
-
},
|
|
34
|
-
// Counterparty name extracted from the narration at upload time.
|
|
35
|
-
payer: {
|
|
36
|
-
type: String
|
|
37
|
-
},
|
|
38
|
-
source: {
|
|
39
|
-
type: String,
|
|
40
|
-
enum: [ 'bank', 'va', 'gateway', 'manual' ],
|
|
41
|
-
default: 'bank',
|
|
42
|
-
},
|
|
43
|
-
status: {
|
|
44
|
-
type: String,
|
|
45
|
-
enum: [ 'reconciled', 'needs_review', 'unmatched', 'excluded' ],
|
|
46
|
-
default: 'unmatched',
|
|
47
|
-
},
|
|
48
|
-
// Filled by the (future) classification pass / manual resolve.
|
|
49
|
-
identifiedClientId: {
|
|
50
|
-
type: String
|
|
51
|
-
},
|
|
52
|
-
identifiedClientName: {
|
|
53
|
-
type: String
|
|
54
|
-
},
|
|
55
|
-
invoice: {
|
|
56
|
-
type: String
|
|
57
|
-
},
|
|
58
|
-
// Mongo _id of the matched invoice — lets the UI open the invoice
|
|
59
|
-
// preview directly from a reconciled transaction.
|
|
60
|
-
invoiceId: {
|
|
61
|
-
type: String
|
|
62
|
-
},
|
|
63
|
-
// When one payment settles MULTIPLE invoices, the exact amount applied
|
|
64
|
-
// to each is recorded here so an Edit/re-reconcile can reverse precisely
|
|
65
|
-
// what was applied. (Single-invoice reconciles also populate this.)
|
|
66
|
-
appliedInvoices: [
|
|
67
|
-
{
|
|
68
|
-
invoiceId: { type: String },
|
|
69
|
-
invoice: { type: String },
|
|
70
|
-
amount: { type: Number },
|
|
71
|
-
},
|
|
72
|
-
],
|
|
73
|
-
resultNote: {
|
|
74
|
-
type: String
|
|
75
|
-
},
|
|
76
|
-
// Set when the team chose "Reach out to customer" in the resolve
|
|
77
|
-
// popup — the row stays in needs_review with a "Reaching out" badge.
|
|
78
|
-
contacted: {
|
|
79
|
-
type: Boolean,
|
|
80
|
-
default: false
|
|
81
|
-
},
|
|
82
|
-
fileName: {
|
|
83
|
-
type: String
|
|
84
|
-
},
|
|
85
|
-
uploadedBy: {
|
|
86
|
-
type: String
|
|
87
|
-
},
|
|
88
|
-
}, {
|
|
89
|
-
strict: true,
|
|
90
|
-
versionKey: false,
|
|
91
|
-
timestamps: true,
|
|
92
|
-
}
|
|
93
|
-
);
|
|
94
|
-
|
|
1
|
+
import mongoose from 'mongoose';
|
|
2
|
+
|
|
3
|
+
// Bank-statement transactions uploaded from the billing "Transactions" tab.
|
|
4
|
+
// Separate from the existing `transaction` collection, which holds payment /
|
|
5
|
+
// wallet (Razorpay) entries. Each row is one statement line; `status` drives
|
|
6
|
+
// the reconciliation buckets shown in the UI.
|
|
7
|
+
const bankTransactionSchema = new mongoose.Schema(
|
|
8
|
+
{
|
|
9
|
+
date: {
|
|
10
|
+
type: Date
|
|
11
|
+
},
|
|
12
|
+
valueDate: {
|
|
13
|
+
type: Date
|
|
14
|
+
},
|
|
15
|
+
narration: {
|
|
16
|
+
type: String
|
|
17
|
+
},
|
|
18
|
+
refNo: {
|
|
19
|
+
type: String,
|
|
20
|
+
index: true
|
|
21
|
+
},
|
|
22
|
+
withdrawalAmt: {
|
|
23
|
+
type: Number,
|
|
24
|
+
default: 0
|
|
25
|
+
},
|
|
26
|
+
depositAmt: {
|
|
27
|
+
type: Number,
|
|
28
|
+
default: 0
|
|
29
|
+
},
|
|
30
|
+
// Signed convenience amount: deposit - withdrawal.
|
|
31
|
+
amount: {
|
|
32
|
+
type: Number
|
|
33
|
+
},
|
|
34
|
+
// Counterparty name extracted from the narration at upload time.
|
|
35
|
+
payer: {
|
|
36
|
+
type: String
|
|
37
|
+
},
|
|
38
|
+
source: {
|
|
39
|
+
type: String,
|
|
40
|
+
enum: [ 'bank', 'va', 'gateway', 'manual' ],
|
|
41
|
+
default: 'bank',
|
|
42
|
+
},
|
|
43
|
+
status: {
|
|
44
|
+
type: String,
|
|
45
|
+
enum: [ 'reconciled', 'needs_review', 'unmatched', 'excluded' ],
|
|
46
|
+
default: 'unmatched',
|
|
47
|
+
},
|
|
48
|
+
// Filled by the (future) classification pass / manual resolve.
|
|
49
|
+
identifiedClientId: {
|
|
50
|
+
type: String
|
|
51
|
+
},
|
|
52
|
+
identifiedClientName: {
|
|
53
|
+
type: String
|
|
54
|
+
},
|
|
55
|
+
invoice: {
|
|
56
|
+
type: String
|
|
57
|
+
},
|
|
58
|
+
// Mongo _id of the matched invoice — lets the UI open the invoice
|
|
59
|
+
// preview directly from a reconciled transaction.
|
|
60
|
+
invoiceId: {
|
|
61
|
+
type: String
|
|
62
|
+
},
|
|
63
|
+
// When one payment settles MULTIPLE invoices, the exact amount applied
|
|
64
|
+
// to each is recorded here so an Edit/re-reconcile can reverse precisely
|
|
65
|
+
// what was applied. (Single-invoice reconciles also populate this.)
|
|
66
|
+
appliedInvoices: [
|
|
67
|
+
{
|
|
68
|
+
invoiceId: { type: String },
|
|
69
|
+
invoice: { type: String },
|
|
70
|
+
amount: { type: Number },
|
|
71
|
+
},
|
|
72
|
+
],
|
|
73
|
+
resultNote: {
|
|
74
|
+
type: String
|
|
75
|
+
},
|
|
76
|
+
// Set when the team chose "Reach out to customer" in the resolve
|
|
77
|
+
// popup — the row stays in needs_review with a "Reaching out" badge.
|
|
78
|
+
contacted: {
|
|
79
|
+
type: Boolean,
|
|
80
|
+
default: false
|
|
81
|
+
},
|
|
82
|
+
fileName: {
|
|
83
|
+
type: String
|
|
84
|
+
},
|
|
85
|
+
uploadedBy: {
|
|
86
|
+
type: String
|
|
87
|
+
},
|
|
88
|
+
}, {
|
|
89
|
+
strict: true,
|
|
90
|
+
versionKey: false,
|
|
91
|
+
timestamps: true,
|
|
92
|
+
}
|
|
93
|
+
);
|
|
94
|
+
|
|
95
95
|
export default mongoose.model('banktransaction', bankTransactionSchema);
|
package/schema/billing.model.js
CHANGED
|
@@ -1,136 +1,136 @@
|
|
|
1
|
-
import mongoose from 'mongoose';
|
|
2
|
-
|
|
3
|
-
const billingSchema = new mongoose.Schema(
|
|
4
|
-
{
|
|
5
|
-
clientId: {
|
|
6
|
-
type: String,
|
|
7
|
-
required: true,
|
|
8
|
-
},
|
|
9
|
-
groupName: {
|
|
10
|
-
type: String,
|
|
11
|
-
default:'Default Group'
|
|
12
|
-
},
|
|
13
|
-
groupTag: {
|
|
14
|
-
type: String,
|
|
15
|
-
enum: ['store','gst'],
|
|
16
|
-
default: 'store'
|
|
17
|
-
},
|
|
18
|
-
registeredCompanyName: {
|
|
19
|
-
type: String,
|
|
20
|
-
},
|
|
21
|
-
gst: {
|
|
22
|
-
type: String,
|
|
23
|
-
},
|
|
24
|
-
addressLineOne: {
|
|
25
|
-
type: String,
|
|
26
|
-
},
|
|
27
|
-
addressLineTwo: {
|
|
28
|
-
type: String,
|
|
29
|
-
},
|
|
30
|
-
city: {
|
|
31
|
-
type: String,
|
|
32
|
-
},
|
|
33
|
-
state: {
|
|
34
|
-
type: String,
|
|
35
|
-
},
|
|
36
|
-
country: {
|
|
37
|
-
type: String,
|
|
38
|
-
},
|
|
39
|
-
pinCode: {
|
|
40
|
-
type: String,
|
|
41
|
-
},
|
|
42
|
-
placeOfSupply: {
|
|
43
|
-
type: String,
|
|
44
|
-
},
|
|
45
|
-
po: {
|
|
46
|
-
type: String,
|
|
47
|
-
},
|
|
48
|
-
stores: {
|
|
49
|
-
type: Array,
|
|
50
|
-
},
|
|
51
|
-
proRata: {
|
|
52
|
-
type: String,
|
|
53
|
-
// 'prorate' = bill for actual working days.
|
|
54
|
-
// 'flat' = bill for the full month regardless of working days.
|
|
55
|
-
// Note: legacy values 'before15' / 'after15' were migrated out via
|
|
56
|
-
// scripts/migrate-billing-prorata-pricing.js. Don't reintroduce them.
|
|
57
|
-
enum: ['prorate','flat'],
|
|
58
|
-
default: 'prorate'
|
|
59
|
-
},
|
|
60
|
-
paymentCategory: {
|
|
61
|
-
type: String,
|
|
62
|
-
enum: ['pre','post'],
|
|
63
|
-
default: 'post'
|
|
64
|
-
},
|
|
65
|
-
currency: {
|
|
66
|
-
type: String,
|
|
67
|
-
enum: ['dollar','inr','singaporedollar','euro','aed'],
|
|
68
|
-
},
|
|
69
|
-
// Drives invoice-generation tax behavior. 'domestic' runs the
|
|
70
|
-
// existing GST/IGST/CGST/SGST logic. 'international' suppresses
|
|
71
|
-
// tax lines entirely (the tax array is left empty so totalAmount
|
|
72
|
-
// equals subtotal). Defaults to 'domestic' so existing records
|
|
73
|
-
// keep their current behavior on read.
|
|
74
|
-
taxCalculationType: {
|
|
75
|
-
type: String,
|
|
76
|
-
enum: ['domestic','international'],
|
|
77
|
-
default: 'domestic'
|
|
78
|
-
},
|
|
79
|
-
isInstallationOneTime: {
|
|
80
|
-
type: Boolean,
|
|
81
|
-
default: false
|
|
82
|
-
},
|
|
83
|
-
installationFee: {
|
|
84
|
-
type: Number,
|
|
85
|
-
},
|
|
86
|
-
paymentCycle: {
|
|
87
|
-
type: String,
|
|
88
|
-
enum: ['monthly','quarter', 'halfYearly', 'yearly'],
|
|
89
|
-
default: 'monthly'
|
|
90
|
-
},
|
|
91
|
-
paymentTerm: {
|
|
92
|
-
type: Number,
|
|
93
|
-
enum: [30, 45, 60, 90],
|
|
94
|
-
default: 30
|
|
95
|
-
},
|
|
96
|
-
generateInvoiceTo: {
|
|
97
|
-
type: Array,
|
|
98
|
-
},
|
|
99
|
-
attachAnnexure: {
|
|
100
|
-
type: Boolean,
|
|
101
|
-
default:false
|
|
102
|
-
},
|
|
103
|
-
isPrimary: {
|
|
104
|
-
type: Boolean
|
|
105
|
-
},
|
|
106
|
-
advanceInvoice: {
|
|
107
|
-
type: Boolean,
|
|
108
|
-
default: false
|
|
109
|
-
},
|
|
110
|
-
// How far ahead an advance invoice is generated when advanceInvoice is on.
|
|
111
|
-
advancePeriod: {
|
|
112
|
-
type: String,
|
|
113
|
-
enum: [ 'monthly', 'quarterly', 'halfyearly', 'yearly' ],
|
|
114
|
-
default: 'monthly'
|
|
115
|
-
},
|
|
116
|
-
products: [
|
|
117
|
-
{
|
|
118
|
-
productName: {
|
|
119
|
-
type: String,
|
|
120
|
-
},
|
|
121
|
-
billingMethod: {
|
|
122
|
-
type: String,
|
|
123
|
-
enum: ['eachStore', 'overallStore'],
|
|
124
|
-
default: 'overallStore'
|
|
125
|
-
}
|
|
126
|
-
}
|
|
127
|
-
]
|
|
128
|
-
},
|
|
129
|
-
{
|
|
130
|
-
strict: true,
|
|
131
|
-
versionKey: false,
|
|
132
|
-
timestamps: true,
|
|
133
|
-
},
|
|
134
|
-
);
|
|
135
|
-
|
|
1
|
+
import mongoose from 'mongoose';
|
|
2
|
+
|
|
3
|
+
const billingSchema = new mongoose.Schema(
|
|
4
|
+
{
|
|
5
|
+
clientId: {
|
|
6
|
+
type: String,
|
|
7
|
+
required: true,
|
|
8
|
+
},
|
|
9
|
+
groupName: {
|
|
10
|
+
type: String,
|
|
11
|
+
default:'Default Group'
|
|
12
|
+
},
|
|
13
|
+
groupTag: {
|
|
14
|
+
type: String,
|
|
15
|
+
enum: ['store','gst'],
|
|
16
|
+
default: 'store'
|
|
17
|
+
},
|
|
18
|
+
registeredCompanyName: {
|
|
19
|
+
type: String,
|
|
20
|
+
},
|
|
21
|
+
gst: {
|
|
22
|
+
type: String,
|
|
23
|
+
},
|
|
24
|
+
addressLineOne: {
|
|
25
|
+
type: String,
|
|
26
|
+
},
|
|
27
|
+
addressLineTwo: {
|
|
28
|
+
type: String,
|
|
29
|
+
},
|
|
30
|
+
city: {
|
|
31
|
+
type: String,
|
|
32
|
+
},
|
|
33
|
+
state: {
|
|
34
|
+
type: String,
|
|
35
|
+
},
|
|
36
|
+
country: {
|
|
37
|
+
type: String,
|
|
38
|
+
},
|
|
39
|
+
pinCode: {
|
|
40
|
+
type: String,
|
|
41
|
+
},
|
|
42
|
+
placeOfSupply: {
|
|
43
|
+
type: String,
|
|
44
|
+
},
|
|
45
|
+
po: {
|
|
46
|
+
type: String,
|
|
47
|
+
},
|
|
48
|
+
stores: {
|
|
49
|
+
type: Array,
|
|
50
|
+
},
|
|
51
|
+
proRata: {
|
|
52
|
+
type: String,
|
|
53
|
+
// 'prorate' = bill for actual working days.
|
|
54
|
+
// 'flat' = bill for the full month regardless of working days.
|
|
55
|
+
// Note: legacy values 'before15' / 'after15' were migrated out via
|
|
56
|
+
// scripts/migrate-billing-prorata-pricing.js. Don't reintroduce them.
|
|
57
|
+
enum: ['prorate','flat'],
|
|
58
|
+
default: 'prorate'
|
|
59
|
+
},
|
|
60
|
+
paymentCategory: {
|
|
61
|
+
type: String,
|
|
62
|
+
enum: ['pre','post'],
|
|
63
|
+
default: 'post'
|
|
64
|
+
},
|
|
65
|
+
currency: {
|
|
66
|
+
type: String,
|
|
67
|
+
enum: ['dollar','inr','singaporedollar','euro','aed'],
|
|
68
|
+
},
|
|
69
|
+
// Drives invoice-generation tax behavior. 'domestic' runs the
|
|
70
|
+
// existing GST/IGST/CGST/SGST logic. 'international' suppresses
|
|
71
|
+
// tax lines entirely (the tax array is left empty so totalAmount
|
|
72
|
+
// equals subtotal). Defaults to 'domestic' so existing records
|
|
73
|
+
// keep their current behavior on read.
|
|
74
|
+
taxCalculationType: {
|
|
75
|
+
type: String,
|
|
76
|
+
enum: ['domestic','international'],
|
|
77
|
+
default: 'domestic'
|
|
78
|
+
},
|
|
79
|
+
isInstallationOneTime: {
|
|
80
|
+
type: Boolean,
|
|
81
|
+
default: false
|
|
82
|
+
},
|
|
83
|
+
installationFee: {
|
|
84
|
+
type: Number,
|
|
85
|
+
},
|
|
86
|
+
paymentCycle: {
|
|
87
|
+
type: String,
|
|
88
|
+
enum: ['monthly','quarter', 'halfYearly', 'yearly'],
|
|
89
|
+
default: 'monthly'
|
|
90
|
+
},
|
|
91
|
+
paymentTerm: {
|
|
92
|
+
type: Number,
|
|
93
|
+
enum: [30, 45, 60, 90],
|
|
94
|
+
default: 30
|
|
95
|
+
},
|
|
96
|
+
generateInvoiceTo: {
|
|
97
|
+
type: Array,
|
|
98
|
+
},
|
|
99
|
+
attachAnnexure: {
|
|
100
|
+
type: Boolean,
|
|
101
|
+
default:false
|
|
102
|
+
},
|
|
103
|
+
isPrimary: {
|
|
104
|
+
type: Boolean
|
|
105
|
+
},
|
|
106
|
+
advanceInvoice: {
|
|
107
|
+
type: Boolean,
|
|
108
|
+
default: false
|
|
109
|
+
},
|
|
110
|
+
// How far ahead an advance invoice is generated when advanceInvoice is on.
|
|
111
|
+
advancePeriod: {
|
|
112
|
+
type: String,
|
|
113
|
+
enum: [ 'monthly', 'quarterly', 'halfyearly', 'yearly' ],
|
|
114
|
+
default: 'monthly'
|
|
115
|
+
},
|
|
116
|
+
products: [
|
|
117
|
+
{
|
|
118
|
+
productName: {
|
|
119
|
+
type: String,
|
|
120
|
+
},
|
|
121
|
+
billingMethod: {
|
|
122
|
+
type: String,
|
|
123
|
+
enum: ['eachStore', 'overallStore'],
|
|
124
|
+
default: 'overallStore'
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
]
|
|
128
|
+
},
|
|
129
|
+
{
|
|
130
|
+
strict: true,
|
|
131
|
+
versionKey: false,
|
|
132
|
+
timestamps: true,
|
|
133
|
+
},
|
|
134
|
+
);
|
|
135
|
+
|
|
136
136
|
export default mongoose.model( 'billing', billingSchema);
|
package/schema/estimate.model.js
CHANGED
|
@@ -1,87 +1,87 @@
|
|
|
1
|
-
import mongoose from 'mongoose';
|
|
2
|
-
|
|
3
|
-
// Estimates (quotations) — generated before an invoice to share projected
|
|
4
|
-
// billing with a client. Mirrors the invoice shape but carries an estimate
|
|
5
|
-
// lifecycle (draft → sent → accepted/declined/expired) and a validity date
|
|
6
|
-
// instead of a due date.
|
|
7
|
-
const estimateSchema = new mongoose.Schema(
|
|
8
|
-
{
|
|
9
|
-
clientId: {
|
|
10
|
-
type: String,
|
|
11
|
-
},
|
|
12
|
-
estimate: {
|
|
13
|
-
type: String, // EST-26-27-00031
|
|
14
|
-
},
|
|
15
|
-
estimateIndex: {
|
|
16
|
-
type: String,
|
|
17
|
-
},
|
|
18
|
-
companyName: {
|
|
19
|
-
type: String,
|
|
20
|
-
},
|
|
21
|
-
companyAddress: {
|
|
22
|
-
type: String,
|
|
23
|
-
},
|
|
24
|
-
PlaceOfSupply: {
|
|
25
|
-
type: String,
|
|
26
|
-
},
|
|
27
|
-
GSTNumber: {
|
|
28
|
-
type: String,
|
|
29
|
-
},
|
|
30
|
-
groupId: {
|
|
31
|
-
type: mongoose.Types.ObjectId,
|
|
32
|
-
},
|
|
33
|
-
groupName: {
|
|
34
|
-
type: String,
|
|
35
|
-
},
|
|
36
|
-
period: {
|
|
37
|
-
type: String, // e.g. "Jun 2026"
|
|
38
|
-
},
|
|
39
|
-
stores: {
|
|
40
|
-
type: Number,
|
|
41
|
-
},
|
|
42
|
-
products: {
|
|
43
|
-
type: Array,
|
|
44
|
-
},
|
|
45
|
-
tax: {
|
|
46
|
-
type: Array,
|
|
47
|
-
},
|
|
48
|
-
amount: {
|
|
49
|
-
type: Number, // excl. GST
|
|
50
|
-
},
|
|
51
|
-
totalAmount: {
|
|
52
|
-
type: Number, // incl. GST
|
|
53
|
-
},
|
|
54
|
-
currency: {
|
|
55
|
-
type: String,
|
|
56
|
-
enum: [ 'dollar', 'inr', 'singaporedollar', 'euro', 'aed' ],
|
|
57
|
-
default: 'inr',
|
|
58
|
-
},
|
|
59
|
-
status: {
|
|
60
|
-
type: String,
|
|
61
|
-
default: 'pending',
|
|
62
|
-
enum: [ 'pending', 'sent', 'accepted', 'declined', 'expired' ],
|
|
63
|
-
},
|
|
64
|
-
createdDate: {
|
|
65
|
-
type: Date,
|
|
66
|
-
},
|
|
67
|
-
validTill: {
|
|
68
|
-
type: Date,
|
|
69
|
-
},
|
|
70
|
-
// Set when an accepted estimate is turned into an invoice.
|
|
71
|
-
convertedInvoice: {
|
|
72
|
-
type: String,
|
|
73
|
-
},
|
|
74
|
-
createdBy: {
|
|
75
|
-
type: String,
|
|
76
|
-
},
|
|
77
|
-
notes: {
|
|
78
|
-
type: String,
|
|
79
|
-
},
|
|
80
|
-
}, {
|
|
81
|
-
strict: true,
|
|
82
|
-
versionKey: false,
|
|
83
|
-
timestamps: true,
|
|
84
|
-
}
|
|
85
|
-
);
|
|
86
|
-
|
|
1
|
+
import mongoose from 'mongoose';
|
|
2
|
+
|
|
3
|
+
// Estimates (quotations) — generated before an invoice to share projected
|
|
4
|
+
// billing with a client. Mirrors the invoice shape but carries an estimate
|
|
5
|
+
// lifecycle (draft → sent → accepted/declined/expired) and a validity date
|
|
6
|
+
// instead of a due date.
|
|
7
|
+
const estimateSchema = new mongoose.Schema(
|
|
8
|
+
{
|
|
9
|
+
clientId: {
|
|
10
|
+
type: String,
|
|
11
|
+
},
|
|
12
|
+
estimate: {
|
|
13
|
+
type: String, // EST-26-27-00031
|
|
14
|
+
},
|
|
15
|
+
estimateIndex: {
|
|
16
|
+
type: String,
|
|
17
|
+
},
|
|
18
|
+
companyName: {
|
|
19
|
+
type: String,
|
|
20
|
+
},
|
|
21
|
+
companyAddress: {
|
|
22
|
+
type: String,
|
|
23
|
+
},
|
|
24
|
+
PlaceOfSupply: {
|
|
25
|
+
type: String,
|
|
26
|
+
},
|
|
27
|
+
GSTNumber: {
|
|
28
|
+
type: String,
|
|
29
|
+
},
|
|
30
|
+
groupId: {
|
|
31
|
+
type: mongoose.Types.ObjectId,
|
|
32
|
+
},
|
|
33
|
+
groupName: {
|
|
34
|
+
type: String,
|
|
35
|
+
},
|
|
36
|
+
period: {
|
|
37
|
+
type: String, // e.g. "Jun 2026"
|
|
38
|
+
},
|
|
39
|
+
stores: {
|
|
40
|
+
type: Number,
|
|
41
|
+
},
|
|
42
|
+
products: {
|
|
43
|
+
type: Array,
|
|
44
|
+
},
|
|
45
|
+
tax: {
|
|
46
|
+
type: Array,
|
|
47
|
+
},
|
|
48
|
+
amount: {
|
|
49
|
+
type: Number, // excl. GST
|
|
50
|
+
},
|
|
51
|
+
totalAmount: {
|
|
52
|
+
type: Number, // incl. GST
|
|
53
|
+
},
|
|
54
|
+
currency: {
|
|
55
|
+
type: String,
|
|
56
|
+
enum: [ 'dollar', 'inr', 'singaporedollar', 'euro', 'aed' ],
|
|
57
|
+
default: 'inr',
|
|
58
|
+
},
|
|
59
|
+
status: {
|
|
60
|
+
type: String,
|
|
61
|
+
default: 'pending',
|
|
62
|
+
enum: [ 'pending', 'sent', 'accepted', 'declined', 'expired' ],
|
|
63
|
+
},
|
|
64
|
+
createdDate: {
|
|
65
|
+
type: Date,
|
|
66
|
+
},
|
|
67
|
+
validTill: {
|
|
68
|
+
type: Date,
|
|
69
|
+
},
|
|
70
|
+
// Set when an accepted estimate is turned into an invoice.
|
|
71
|
+
convertedInvoice: {
|
|
72
|
+
type: String,
|
|
73
|
+
},
|
|
74
|
+
createdBy: {
|
|
75
|
+
type: String,
|
|
76
|
+
},
|
|
77
|
+
notes: {
|
|
78
|
+
type: String,
|
|
79
|
+
},
|
|
80
|
+
}, {
|
|
81
|
+
strict: true,
|
|
82
|
+
versionKey: false,
|
|
83
|
+
timestamps: true,
|
|
84
|
+
}
|
|
85
|
+
);
|
|
86
|
+
|
|
87
87
|
export default mongoose.model( 'estimate', estimateSchema );
|
|
@@ -225,4 +225,9 @@ const fixtureConfigSchema = new mongoose.Schema(
|
|
|
225
225
|
},
|
|
226
226
|
);
|
|
227
227
|
|
|
228
|
+
// Indexes — covers processFixtureTemplates / submitFixtureFeedback's
|
|
229
|
+
// {clientId, crestMapKey, templateType} aggregate $match. masterTemplateId is
|
|
230
|
+
// already field-level indexed.
|
|
231
|
+
fixtureConfigSchema.index( { clientId: 1, crestMapKey: 1, templateType: 1 } );
|
|
232
|
+
|
|
228
233
|
export default mongoose.model('fixtureConfig', fixtureConfigSchema);
|
|
@@ -78,4 +78,9 @@ const fixtureShelfSchema = new mongoose.Schema(
|
|
|
78
78
|
},
|
|
79
79
|
);
|
|
80
80
|
|
|
81
|
+
// Indexes — {fixtureId} covers deleteMany on fixture replace; {floorId} covers
|
|
82
|
+
// zone-response sync; {planoId,floorId} for bulk sweeps. Existing field-level
|
|
83
|
+
// index:true on fixtureId/floorId/planoId is left in place.
|
|
84
|
+
fixtureShelfSchema.index( { planoId: 1, floorId: 1 } );
|
|
85
|
+
|
|
81
86
|
export default mongoose.model('fixtureShelf', fixtureShelfSchema);
|