@jsdev_ninja/core 0.12.11 → 0.13.13

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.
@@ -1 +1 @@
1
- {"version":3,"file":"engine.d.ts","sourceRoot":"","sources":["../../../lib/entities/Discount/engine.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,eAAe,EAAmB,MAAM,SAAS,CAAC;AAGtE,qBAAa,cAAc;IACzB,MAAM,CAAC,kBAAkB,CACvB,IAAI,EAAE,KAAK,CAAC;QACV,MAAM,EAAE,MAAM,CAAC;QACf,OAAO,EAAE;YACP,EAAE,EAAE,MAAM,CAAC;YACX,KAAK,EAAE,MAAM,CAAC;SACf,CAAC;KACH,CAAC,EACF,SAAS,EAAE,SAAS,EAAE,EACtB,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC7B;QACD,KAAK,EAAE,KAAK,CAAC;YACX,MAAM,EAAE,MAAM,CAAC;YACf,OAAO,EAAE;gBACP,EAAE,EAAE,MAAM,CAAC;gBACX,KAAK,EAAE,MAAM,CAAC;aACf,CAAC;YACF,aAAa,EAAE,MAAM,CAAC;YACtB,UAAU,EAAE,MAAM,CAAC;YACnB,aAAa,EAAE,MAAM,CAAC;YACtB,gBAAgB,EAAE,MAAM,EAAE,CAAC;SAC5B,CAAC,CAAC;QACH,aAAa,EAAE,MAAM,CAAC;QACtB,gBAAgB,EAAE,eAAe,EAAE,CAAC;KACrC;IAoDD,OAAO,CAAC,MAAM,CAAC,qBAAqB;IASpC,OAAO,CAAC,MAAM,CAAC,oBAAoB;IA6BnC,MAAM,CAAC,gBAAgB,CAAC,QAAQ,EAAE,SAAS,GAAG,OAAO;IAOrD,MAAM,CAAC,kBAAkB,CAAC,SAAS,EAAE,SAAS,EAAE,GAAG,SAAS,EAAE;CAG/D"}
1
+ {"version":3,"file":"engine.d.ts","sourceRoot":"","sources":["../../../lib/entities/Discount/engine.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,eAAe,EAAmB,MAAM,SAAS,CAAC;AAYtE,qBAAa,cAAc;IAC1B,MAAM,CAAC,kBAAkB,CACxB,IAAI,EAAE,KAAK,CAAC;QACX,MAAM,EAAE,MAAM,CAAC;QACf,OAAO,EAAE;YACR,EAAE,EAAE,MAAM,CAAC;YACX,KAAK,EAAE,MAAM,CAAC;SACd,CAAC;KACF,CAAC,EACF,SAAS,EAAE,SAAS,EAAE,EACtB,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC5B;QACF,KAAK,EAAE,KAAK,CAAC;YACZ,MAAM,EAAE,MAAM,CAAC;YACf,OAAO,EAAE;gBACR,EAAE,EAAE,MAAM,CAAC;gBACX,KAAK,EAAE,MAAM,CAAC;aACd,CAAC;YACF,aAAa,EAAE,MAAM,CAAC;YACtB,UAAU,EAAE,MAAM,CAAC;YACnB,aAAa,EAAE,MAAM,CAAC;YACtB,gBAAgB,EAAE,MAAM,EAAE,CAAC;SAC3B,CAAC,CAAC;QACH,aAAa,EAAE,MAAM,CAAC;QACtB,gBAAgB,EAAE,eAAe,EAAE,CAAC;KACpC;IAuDD,OAAO,CAAC,MAAM,CAAC,qBAAqB;IAOpC,OAAO,CAAC,MAAM,CAAC,oBAAoB;IA8BnC,MAAM,CAAC,gBAAgB,CAAC,QAAQ,EAAE,SAAS,GAAG,OAAO;IAKrD,MAAM,CAAC,kBAAkB,CAAC,SAAS,EAAE,SAAS,EAAE,GAAG,SAAS,EAAE;CAG9D"}
@@ -1,4 +1,12 @@
1
1
  import { DiscountStrategyFactory } from "./factory";
2
+ // discount engine - calculate discounts and return final prices
3
+ // should register all discount types
4
+ // should receive all store discounts
5
+ // should check active discount that should be applied on cart
6
+ // should find best discount per product
7
+ // should apply discount to if stackable or best one
8
+ // any applyd discount should mark products that effected and price before and after and average price per product in cart
9
+ // should return items list with all calculations and final prices and discounts
2
10
  export class DiscountEngine {
3
11
  static calculateDiscounts(cart, discounts, user) {
4
12
  const context = {
@@ -18,6 +26,7 @@ export class DiscountEngine {
18
26
  if (!strategy.canApply(discount, context))
19
27
  continue;
20
28
  // Check if discount is stackable
29
+ // todo
21
30
  if (!discount.conditions?.stackable && appliedDiscounts.length > 0)
22
31
  continue;
23
32
  // Calculate discount
@@ -45,15 +54,13 @@ export class DiscountEngine {
45
54
  }
46
55
  static filterActiveDiscounts(discounts) {
47
56
  const now = Date.now();
48
- return discounts.filter(discount => discount.active &&
49
- discount.startDate <= now &&
50
- discount.endDate >= now);
57
+ return discounts.filter((discount) => discount.active && discount.startDate <= now && discount.endDate >= now);
51
58
  }
52
59
  static calculateFinalPrices(cart, appliedDiscounts) {
53
- return cart.map(item => {
54
- const itemDiscounts = appliedDiscounts.filter(discount => discount.affectedItems.some(affected => affected.productId === item.product.id));
60
+ return cart.map((item) => {
61
+ const itemDiscounts = appliedDiscounts.filter((discount) => discount.affectedItems.some((affected) => affected.productId === item.product.id));
55
62
  const totalItemDiscount = itemDiscounts.reduce((sum, discount) => {
56
- const affectedItem = discount.affectedItems.find(affected => affected.productId === item.product.id);
63
+ const affectedItem = discount.affectedItems.find((affected) => affected.productId === item.product.id);
57
64
  return sum + (affectedItem?.discountAmount || 0);
58
65
  }, 0);
59
66
  const discountPerUnit = totalItemDiscount / item.amount;
@@ -64,15 +71,13 @@ export class DiscountEngine {
64
71
  originalPrice: Number(item.product.price.toFixed(2)),
65
72
  finalPrice: Number(Math.max(0, finalPrice).toFixed(2)),
66
73
  finalDiscount: Number(totalItemDiscount.toFixed(2)),
67
- appliedDiscounts: itemDiscounts.map(d => d.discountId),
74
+ appliedDiscounts: itemDiscounts.map((d) => d.discountId),
68
75
  };
69
76
  });
70
77
  }
71
78
  static isDiscountActive(discount) {
72
79
  const now = Date.now();
73
- return discount.active &&
74
- discount.startDate <= now &&
75
- discount.endDate >= now;
80
+ return discount.active && discount.startDate <= now && discount.endDate >= now;
76
81
  }
77
82
  static getActiveDiscounts(discounts) {
78
83
  return this.filterActiveDiscounts(discounts);
@@ -545,6 +545,7 @@ export declare const OrderSchema: z.ZodObject<{
545
545
  cartDiscount: z.ZodNumber;
546
546
  cartTotal: z.ZodNumber;
547
547
  cartVat: z.ZodNumber;
548
+ deliveryPrice: z.ZodOptional<z.ZodNumber>;
548
549
  }, "strip", z.ZodTypeAny, {
549
550
  id: string;
550
551
  items: {
@@ -643,6 +644,7 @@ export declare const OrderSchema: z.ZodObject<{
643
644
  cartDiscount: number;
644
645
  cartTotal: number;
645
646
  cartVat: number;
647
+ deliveryPrice?: number | undefined;
646
648
  }, {
647
649
  id: string;
648
650
  items: {
@@ -741,6 +743,7 @@ export declare const OrderSchema: z.ZodObject<{
741
743
  cartDiscount: number;
742
744
  cartTotal: number;
743
745
  cartVat: number;
746
+ deliveryPrice?: number | undefined;
744
747
  }>;
745
748
  originalAmount: z.ZodOptional<z.ZodNumber>;
746
749
  actualAmount: z.ZodOptional<z.ZodNumber>;
@@ -786,6 +789,7 @@ export declare const OrderSchema: z.ZodObject<{
786
789
  createdDate: z.ZodNumber;
787
790
  lastActivityDate: z.ZodNumber;
788
791
  paymentType: z.ZodEnum<["default", "delayed"]>;
792
+ organizationId: z.ZodOptional<z.ZodString>;
789
793
  }, "strip", z.ZodTypeAny, {
790
794
  type: "Profile";
791
795
  id: string;
@@ -810,6 +814,7 @@ export declare const OrderSchema: z.ZodObject<{
810
814
  apartmentEnterNumber: string;
811
815
  apartmentNumber: string;
812
816
  } | undefined;
817
+ organizationId?: string | undefined;
813
818
  }, {
814
819
  type: "Profile";
815
820
  id: string;
@@ -834,6 +839,7 @@ export declare const OrderSchema: z.ZodObject<{
834
839
  apartmentEnterNumber: string;
835
840
  apartmentNumber: string;
836
841
  } | undefined;
842
+ organizationId?: string | undefined;
837
843
  }>;
838
844
  nameOnInvoice: z.ZodOptional<z.ZodString>;
839
845
  clientComment: z.ZodOptional<z.ZodString>;
@@ -944,6 +950,7 @@ export declare const OrderSchema: z.ZodObject<{
944
950
  cartDiscount: number;
945
951
  cartTotal: number;
946
952
  cartVat: number;
953
+ deliveryPrice?: number | undefined;
947
954
  };
948
955
  deliveryDate: number;
949
956
  client: {
@@ -970,6 +977,7 @@ export declare const OrderSchema: z.ZodObject<{
970
977
  apartmentEnterNumber: string;
971
978
  apartmentNumber: string;
972
979
  } | undefined;
980
+ organizationId?: string | undefined;
973
981
  };
974
982
  originalAmount?: number | undefined;
975
983
  actualAmount?: number | undefined;
@@ -1082,6 +1090,7 @@ export declare const OrderSchema: z.ZodObject<{
1082
1090
  cartDiscount: number;
1083
1091
  cartTotal: number;
1084
1092
  cartVat: number;
1093
+ deliveryPrice?: number | undefined;
1085
1094
  };
1086
1095
  deliveryDate: number;
1087
1096
  client: {
@@ -1108,6 +1117,7 @@ export declare const OrderSchema: z.ZodObject<{
1108
1117
  apartmentEnterNumber: string;
1109
1118
  apartmentNumber: string;
1110
1119
  } | undefined;
1120
+ organizationId?: string | undefined;
1111
1121
  };
1112
1122
  originalAmount?: number | undefined;
1113
1123
  actualAmount?: number | undefined;
@@ -1 +1 @@
1
- {"version":3,"file":"Order.d.ts","sourceRoot":"","sources":["../../lib/entities/Order.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAaxB,eAAO,MAAM,WAAW;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA+BtB,CAAC;AAEH,MAAM,MAAM,MAAM,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,WAAW,CAAC,CAAC"}
1
+ {"version":3,"file":"Order.d.ts","sourceRoot":"","sources":["../../lib/entities/Order.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAaxB,eAAO,MAAM,WAAW;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAgCtB,CAAC;AAEH,MAAM,MAAM,MAAM,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,WAAW,CAAC,CAAC"}
@@ -31,6 +31,7 @@ export const OrderSchema = z.object({
31
31
  cartDiscount: z.number(),
32
32
  cartTotal: z.number(),
33
33
  cartVat: z.number(),
34
+ deliveryPrice: z.number().optional(),
34
35
  }),
35
36
  originalAmount: z.number().positive().optional(), // what client pay
36
37
  actualAmount: z.number().positive().optional(), // what store charge
@@ -0,0 +1,34 @@
1
+ import { z } from "zod";
2
+ export declare const OrganizationSchema: z.ZodObject<{
3
+ id: z.ZodString;
4
+ name: z.ZodString;
5
+ discountPercentage: z.ZodOptional<z.ZodNumber>;
6
+ nameOnInvoice: z.ZodOptional<z.ZodString>;
7
+ }, "strip", z.ZodTypeAny, {
8
+ id: string;
9
+ name: string;
10
+ nameOnInvoice?: string | undefined;
11
+ discountPercentage?: number | undefined;
12
+ }, {
13
+ id: string;
14
+ name: string;
15
+ nameOnInvoice?: string | undefined;
16
+ discountPercentage?: number | undefined;
17
+ }>;
18
+ export declare const NewOrganizationSchema: z.ZodObject<Omit<{
19
+ id: z.ZodString;
20
+ name: z.ZodString;
21
+ discountPercentage: z.ZodOptional<z.ZodNumber>;
22
+ nameOnInvoice: z.ZodOptional<z.ZodString>;
23
+ }, "id">, "strip", z.ZodTypeAny, {
24
+ name: string;
25
+ nameOnInvoice?: string | undefined;
26
+ discountPercentage?: number | undefined;
27
+ }, {
28
+ name: string;
29
+ nameOnInvoice?: string | undefined;
30
+ discountPercentage?: number | undefined;
31
+ }>;
32
+ export type TNewOrganization = z.infer<typeof NewOrganizationSchema>;
33
+ export type TOrganization = z.infer<typeof OrganizationSchema>;
34
+ //# sourceMappingURL=Organization.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Organization.d.ts","sourceRoot":"","sources":["../../lib/entities/Organization.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,eAAO,MAAM,kBAAkB;;;;;;;;;;;;;;;EAK7B,CAAC;AAEH,eAAO,MAAM,qBAAqB;;;;;;;;;;;;;EAAwC,CAAC;AAE3E,MAAM,MAAM,gBAAgB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,qBAAqB,CAAC,CAAC;AACrE,MAAM,MAAM,aAAa,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,kBAAkB,CAAC,CAAC"}
@@ -0,0 +1,9 @@
1
+ import { z } from "zod";
2
+ // client organization for clients
3
+ export const OrganizationSchema = z.object({
4
+ id: z.string(),
5
+ name: z.string(),
6
+ discountPercentage: z.number().positive().min(0).max(100).optional(),
7
+ nameOnInvoice: z.string().optional(),
8
+ });
9
+ export const NewOrganizationSchema = OrganizationSchema.omit({ id: true });
@@ -41,6 +41,7 @@ export declare const ProfileSchema: z.ZodObject<{
41
41
  createdDate: z.ZodNumber;
42
42
  lastActivityDate: z.ZodNumber;
43
43
  paymentType: z.ZodEnum<["default", "delayed"]>;
44
+ organizationId: z.ZodOptional<z.ZodString>;
44
45
  }, "strip", z.ZodTypeAny, {
45
46
  type: "Profile";
46
47
  id: string;
@@ -65,6 +66,7 @@ export declare const ProfileSchema: z.ZodObject<{
65
66
  apartmentEnterNumber: string;
66
67
  apartmentNumber: string;
67
68
  } | undefined;
69
+ organizationId?: string | undefined;
68
70
  }, {
69
71
  type: "Profile";
70
72
  id: string;
@@ -89,6 +91,7 @@ export declare const ProfileSchema: z.ZodObject<{
89
91
  apartmentEnterNumber: string;
90
92
  apartmentNumber: string;
91
93
  } | undefined;
94
+ organizationId?: string | undefined;
92
95
  }>;
93
96
  export type TProfile = z.infer<typeof ProfileSchema>;
94
97
  export declare function createEmptyProfile(): TProfile;
@@ -1 +1 @@
1
- {"version":3,"file":"Profile.d.ts","sourceRoot":"","sources":["../../lib/entities/Profile.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAIxB,eAAO,MAAM,wBAAwB,mCAEnC,CAAC;AACH,MAAM,MAAM,mBAAmB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,wBAAwB,CAAC,CAAC;AAE3E,eAAO,MAAM,aAAa;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAgBxB,CAAC;AAEH,MAAM,MAAM,QAAQ,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,aAAa,CAAC,CAAC;AAErD,wBAAgB,kBAAkB,IAAI,QAAQ,CAyB7C"}
1
+ {"version":3,"file":"Profile.d.ts","sourceRoot":"","sources":["../../lib/entities/Profile.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAIxB,eAAO,MAAM,wBAAwB,mCAEnC,CAAC;AACH,MAAM,MAAM,mBAAmB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,wBAAwB,CAAC,CAAC;AAE3E,eAAO,MAAM,aAAa;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAiBxB,CAAC;AAEH,MAAM,MAAM,QAAQ,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,aAAa,CAAC,CAAC;AAErD,wBAAgB,kBAAkB,IAAI,QAAQ,CAyB7C"}
@@ -20,6 +20,7 @@ export const ProfileSchema = z.object({
20
20
  createdDate: z.number(),
21
21
  lastActivityDate: z.number(),
22
22
  paymentType: ProfilePaymentTypeSchema,
23
+ organizationId: z.string().optional(),
23
24
  });
24
25
  export function createEmptyProfile() {
25
26
  return {
@@ -25,9 +25,9 @@ export declare const StoreSchema: z.ZodObject<{
25
25
  allowAnonymousClients: boolean;
26
26
  isVatIncludedInPrice: boolean;
27
27
  clientTypes: ("company" | "individual")[];
28
+ deliveryPrice?: number | undefined;
28
29
  minimumOrder?: number | undefined;
29
30
  freeDeliveryPrice?: number | undefined;
30
- deliveryPrice?: number | undefined;
31
31
  }, {
32
32
  id: string;
33
33
  companyId: string;
@@ -39,9 +39,9 @@ export declare const StoreSchema: z.ZodObject<{
39
39
  allowAnonymousClients: boolean;
40
40
  isVatIncludedInPrice: boolean;
41
41
  clientTypes: ("company" | "individual")[];
42
+ deliveryPrice?: number | undefined;
42
43
  minimumOrder?: number | undefined;
43
44
  freeDeliveryPrice?: number | undefined;
44
- deliveryPrice?: number | undefined;
45
45
  }>;
46
46
  export type TStore = z.infer<typeof StoreSchema>;
47
47
  //# sourceMappingURL=Store.d.ts.map
@@ -10,4 +10,5 @@ export * from "./Product";
10
10
  export * from "./Profile";
11
11
  export * from "./Store";
12
12
  export * from "./Discount";
13
+ export * from "./Organization";
13
14
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../lib/entities/index.ts"],"names":[],"mappings":"AAAA,cAAc,WAAW,CAAC;AAC1B,cAAc,SAAS,CAAC;AACxB,cAAc,QAAQ,CAAC;AACvB,cAAc,YAAY,CAAC;AAC3B,cAAc,WAAW,CAAC;AAC1B,cAAc,mBAAmB,CAAC;AAClC,cAAc,UAAU,CAAC;AACzB,cAAc,SAAS,CAAC;AACxB,cAAc,WAAW,CAAC;AAC1B,cAAc,WAAW,CAAC;AAC1B,cAAc,SAAS,CAAC;AACxB,cAAc,YAAY,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../lib/entities/index.ts"],"names":[],"mappings":"AAAA,cAAc,WAAW,CAAC;AAC1B,cAAc,SAAS,CAAC;AACxB,cAAc,QAAQ,CAAC;AACvB,cAAc,YAAY,CAAC;AAC3B,cAAc,WAAW,CAAC;AAC1B,cAAc,mBAAmB,CAAC;AAClC,cAAc,UAAU,CAAC;AACzB,cAAc,SAAS,CAAC;AACxB,cAAc,WAAW,CAAC;AAC1B,cAAc,WAAW,CAAC;AAC1B,cAAc,SAAS,CAAC;AACxB,cAAc,YAAY,CAAC;AAC3B,cAAc,gBAAgB,CAAC"}
@@ -10,3 +10,4 @@ export * from "./Product";
10
10
  export * from "./Profile";
11
11
  export * from "./Store";
12
12
  export * from "./Discount";
13
+ export * from "./Organization";
@@ -13,6 +13,7 @@ export declare const storeCollections: {
13
13
  readonly payments: "payments";
14
14
  readonly settings: "settings";
15
15
  readonly discounts: "discounts";
16
+ readonly organizations: "organizations";
16
17
  };
17
18
  export declare const FirestoreApi: {
18
19
  systemCollections: {
@@ -30,6 +31,7 @@ export declare const FirestoreApi: {
30
31
  readonly payments: "payments";
31
32
  readonly settings: "settings";
32
33
  readonly discounts: "discounts";
34
+ readonly organizations: "organizations";
33
35
  };
34
36
  getPath: ({ companyId, storeId, collectionName, id, }: {
35
37
  companyId: string;
@@ -56,6 +58,7 @@ export declare const FirebaseAPI: {
56
58
  readonly payments: "payments";
57
59
  readonly settings: "settings";
58
60
  readonly discounts: "discounts";
61
+ readonly organizations: "organizations";
59
62
  };
60
63
  getPath: ({ companyId, storeId, collectionName, id, }: {
61
64
  companyId: string;
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../lib/firebase-api/index.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,iBAAiB;;;CAGpB,CAAC;AAEX,eAAO,MAAM,gBAAgB;;;;;;;;;;;CAWnB,CAAC;AAEX,eAAO,MAAM,YAAY;;;;;;;;;;;;;;;;;2DASrB;QACF,SAAS,EAAE,MAAM,CAAC;QAClB,OAAO,EAAE,MAAM,CAAC;QAChB,cAAc,EAAE,MAAM,OAAO,gBAAgB,CAAC;QAC9C,EAAE,CAAC,EAAE,MAAM,CAAC;KACZ;iCAI4B,MAAM,OAAO,gBAAgB;CAG1D,CAAC;AAEF,eAAO,MAAM,WAAW;;;;;;;;;;;;;;;;;;+DAdpB;YACF,SAAS,EAAE,MAAM,CAAC;YAClB,OAAO,EAAE,MAAM,CAAC;YAChB,cAAc,EAAE,MAAM,OAAO,gBAAgB,CAAC;YAC9C,EAAE,CAAC,EAAE,MAAM,CAAC;SACZ;qCAI4B,MAAM,OAAO,gBAAgB;;CAO1D,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../lib/firebase-api/index.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,iBAAiB;;;CAGpB,CAAC;AAEX,eAAO,MAAM,gBAAgB;;;;;;;;;;;;CAYnB,CAAC;AAEX,eAAO,MAAM,YAAY;;;;;;;;;;;;;;;;;;2DASrB;QACF,SAAS,EAAE,MAAM,CAAC;QAClB,OAAO,EAAE,MAAM,CAAC;QAChB,cAAc,EAAE,MAAM,OAAO,gBAAgB,CAAC;QAC9C,EAAE,CAAC,EAAE,MAAM,CAAC;KACZ;iCAI4B,MAAM,OAAO,gBAAgB;CAG1D,CAAC;AAEF,eAAO,MAAM,WAAW;;;;;;;;;;;;;;;;;;;+DAdpB;YACF,SAAS,EAAE,MAAM,CAAC;YAClB,OAAO,EAAE,MAAM,CAAC;YAChB,cAAc,EAAE,MAAM,OAAO,gBAAgB,CAAC;YAC9C,EAAE,CAAC,EAAE,MAAM,CAAC;SACZ;qCAI4B,MAAM,OAAO,gBAAgB;;CAO1D,CAAC"}
@@ -13,6 +13,7 @@ export const storeCollections = {
13
13
  payments: "payments",
14
14
  settings: "settings",
15
15
  discounts: "discounts",
16
+ organizations: "organizations",
16
17
  };
17
18
  export const FirestoreApi = {
18
19
  systemCollections,
@@ -1 +1 @@
1
- {"root":["../lib/index.tsx","../lib/entities/address.ts","../lib/entities/atoms.ts","../lib/entities/cart.ts","../lib/entities/category.ts","../lib/entities/company.ts","../lib/entities/favoriteproduct.ts","../lib/entities/locale.ts","../lib/entities/order.ts","../lib/entities/product.ts","../lib/entities/profile.ts","../lib/entities/store.ts","../lib/entities/index.ts","../lib/entities/discount/engine.ts","../lib/entities/discount/factory.ts","../lib/entities/discount/index.ts","../lib/entities/discount/strategy.ts","../lib/entities/discount/types.ts","../lib/entities/discount/utils.ts","../lib/entities/discount/__tests__/engine.test.ts","../lib/entities/discount/__tests__/factory.test.ts","../lib/entities/discount/__tests__/integration.test.ts","../lib/entities/discount/__tests__/simple.test.ts","../lib/entities/discount/__tests__/utils.test.ts","../lib/entities/discount/strategies/bundlestrategy.ts","../lib/entities/discount/strategies/__tests__/bundlestrategy.test.ts","../lib/firebase-api/app.ts","../lib/firebase-api/index.ts","../lib/utils/index.ts"],"version":"5.7.3"}
1
+ {"root":["../lib/index.tsx","../lib/entities/address.ts","../lib/entities/atoms.ts","../lib/entities/cart.ts","../lib/entities/category.ts","../lib/entities/company.ts","../lib/entities/favoriteproduct.ts","../lib/entities/locale.ts","../lib/entities/order.ts","../lib/entities/organization.ts","../lib/entities/product.ts","../lib/entities/profile.ts","../lib/entities/store.ts","../lib/entities/index.ts","../lib/entities/discount/engine.ts","../lib/entities/discount/factory.ts","../lib/entities/discount/index.ts","../lib/entities/discount/strategy.ts","../lib/entities/discount/types.ts","../lib/entities/discount/utils.ts","../lib/entities/discount/__tests__/engine.test.ts","../lib/entities/discount/__tests__/factory.test.ts","../lib/entities/discount/__tests__/integration.test.ts","../lib/entities/discount/__tests__/simple.test.ts","../lib/entities/discount/__tests__/utils.test.ts","../lib/entities/discount/strategies/bundlestrategy.ts","../lib/entities/discount/strategies/__tests__/bundlestrategy.test.ts","../lib/firebase-api/app.ts","../lib/firebase-api/index.ts","../lib/utils/index.ts"],"version":"5.7.3"}
@@ -1,129 +1,138 @@
1
1
  import { TDiscount, AppliedDiscount, DiscountContext } from "./types";
2
2
  import { DiscountStrategyFactory } from "./factory";
3
3
 
4
+ // discount engine - calculate discounts and return final prices
5
+ // should register all discount types
6
+ // should receive all store discounts
7
+ // should check active discount that should be applied on cart
8
+ // should find best discount per product
9
+ // should apply discount to if stackable or best one
10
+ // any applyd discount should mark products that effected and price before and after and average price per product in cart
11
+ // should return items list with all calculations and final prices and discounts
12
+
4
13
  export class DiscountEngine {
5
- static calculateDiscounts(
6
- cart: Array<{
7
- amount: number;
8
- product: {
9
- id: string;
10
- price: number;
11
- };
12
- }>,
13
- discounts: TDiscount[],
14
- user?: Record<string, unknown>
15
- ): {
16
- items: Array<{
17
- amount: number;
18
- product: {
19
- id: string;
20
- price: number;
21
- };
22
- originalPrice: number;
23
- finalPrice: number;
24
- finalDiscount: number;
25
- appliedDiscounts: string[];
26
- }>;
27
- totalDiscount: number;
28
- appliedDiscounts: AppliedDiscount[];
29
- } {
30
- const context: DiscountContext = {
31
- cart,
32
- user,
33
- appliedDiscounts: [],
34
- };
35
-
36
- // Filter active discounts
37
- const activeDiscounts = this.filterActiveDiscounts(discounts);
38
-
39
- // Apply discounts
40
- const appliedDiscounts: AppliedDiscount[] = [];
41
-
42
- for (const discount of activeDiscounts) {
43
- const strategy = DiscountStrategyFactory.getStrategy(discount);
44
- if (!strategy) continue;
45
-
46
- // Check if discount can be applied
47
- if (!strategy.canApply(discount, context)) continue;
48
-
49
- // Check if discount is stackable
50
- if (!discount.conditions?.stackable && appliedDiscounts.length > 0) continue;
51
-
52
- // Calculate discount
53
- const result = strategy.calculate(discount, context);
54
- if (!result.applicable) continue;
55
-
56
- // Apply discount
57
- appliedDiscounts.push({
58
- discountId: discount.id,
59
- discountName: discount.name[0]?.value || "Discount",
60
- discountAmount: Number(result.discountAmount.toFixed(2)),
61
- affectedItems: result.affectedItems,
62
- });
63
-
64
- // Update context for next iteration
65
- context.appliedDiscounts = appliedDiscounts;
66
- }
67
-
68
- // Calculate final prices
69
- const items = this.calculateFinalPrices(cart, appliedDiscounts);
70
-
71
- const totalDiscount = appliedDiscounts.reduce((sum, discount) =>
72
- sum + discount.discountAmount, 0);
73
-
74
- return {
75
- items,
76
- totalDiscount: Number(totalDiscount.toFixed(2)),
77
- appliedDiscounts,
78
- };
79
- }
80
-
81
- private static filterActiveDiscounts(discounts: TDiscount[]): TDiscount[] {
82
- const now = Date.now();
83
- return discounts.filter(discount =>
84
- discount.active &&
85
- discount.startDate <= now &&
86
- discount.endDate >= now
87
- );
88
- }
89
-
90
- private static calculateFinalPrices(
91
- cart: DiscountContext["cart"],
92
- appliedDiscounts: AppliedDiscount[]
93
- ) {
94
- return cart.map(item => {
95
- const itemDiscounts = appliedDiscounts.filter(discount =>
96
- discount.affectedItems.some(affected => affected.productId === item.product.id)
97
- );
98
-
99
- const totalItemDiscount = itemDiscounts.reduce((sum, discount) => {
100
- const affectedItem = discount.affectedItems.find(affected =>
101
- affected.productId === item.product.id);
102
- return sum + (affectedItem?.discountAmount || 0);
103
- }, 0);
104
-
105
- const discountPerUnit = totalItemDiscount / item.amount;
106
- const finalPrice = item.product.price - discountPerUnit;
107
-
108
- return {
109
- amount: item.amount,
110
- product: item.product,
111
- originalPrice: Number(item.product.price.toFixed(2)),
112
- finalPrice: Number(Math.max(0, finalPrice).toFixed(2)),
113
- finalDiscount: Number(totalItemDiscount.toFixed(2)),
114
- appliedDiscounts: itemDiscounts.map(d => d.discountId),
115
- };
116
- });
117
- }
118
-
119
- static isDiscountActive(discount: TDiscount): boolean {
120
- const now = Date.now();
121
- return discount.active &&
122
- discount.startDate <= now &&
123
- discount.endDate >= now;
124
- }
125
-
126
- static getActiveDiscounts(discounts: TDiscount[]): TDiscount[] {
127
- return this.filterActiveDiscounts(discounts);
128
- }
129
- }
14
+ static calculateDiscounts(
15
+ cart: Array<{
16
+ amount: number;
17
+ product: {
18
+ id: string;
19
+ price: number;
20
+ };
21
+ }>,
22
+ discounts: TDiscount[],
23
+ user?: Record<string, unknown>
24
+ ): {
25
+ items: Array<{
26
+ amount: number;
27
+ product: {
28
+ id: string;
29
+ price: number;
30
+ };
31
+ originalPrice: number;
32
+ finalPrice: number;
33
+ finalDiscount: number;
34
+ appliedDiscounts: string[];
35
+ }>;
36
+ totalDiscount: number;
37
+ appliedDiscounts: AppliedDiscount[];
38
+ } {
39
+ const context: DiscountContext = {
40
+ cart,
41
+ user,
42
+ appliedDiscounts: [],
43
+ };
44
+
45
+ // Filter active discounts
46
+ const activeDiscounts = this.filterActiveDiscounts(discounts);
47
+
48
+ // Apply discounts
49
+ const appliedDiscounts: AppliedDiscount[] = [];
50
+
51
+ for (const discount of activeDiscounts) {
52
+ const strategy = DiscountStrategyFactory.getStrategy(discount);
53
+ if (!strategy) continue;
54
+
55
+ // Check if discount can be applied
56
+ if (!strategy.canApply(discount, context)) continue;
57
+
58
+ // Check if discount is stackable
59
+ // todo
60
+ if (!discount.conditions?.stackable && appliedDiscounts.length > 0) continue;
61
+
62
+ // Calculate discount
63
+ const result = strategy.calculate(discount, context);
64
+ if (!result.applicable) continue;
65
+
66
+ // Apply discount
67
+ appliedDiscounts.push({
68
+ discountId: discount.id,
69
+ discountName: discount.name[0]?.value || "Discount",
70
+ discountAmount: Number(result.discountAmount.toFixed(2)),
71
+ affectedItems: result.affectedItems,
72
+ });
73
+
74
+ // Update context for next iteration
75
+ context.appliedDiscounts = appliedDiscounts;
76
+ }
77
+
78
+ // Calculate final prices
79
+ const items = this.calculateFinalPrices(cart, appliedDiscounts);
80
+
81
+ const totalDiscount = appliedDiscounts.reduce(
82
+ (sum, discount) => sum + discount.discountAmount,
83
+ 0
84
+ );
85
+
86
+ return {
87
+ items,
88
+ totalDiscount: Number(totalDiscount.toFixed(2)),
89
+ appliedDiscounts,
90
+ };
91
+ }
92
+
93
+ private static filterActiveDiscounts(discounts: TDiscount[]): TDiscount[] {
94
+ const now = Date.now();
95
+ return discounts.filter(
96
+ (discount) => discount.active && discount.startDate <= now && discount.endDate >= now
97
+ );
98
+ }
99
+
100
+ private static calculateFinalPrices(
101
+ cart: DiscountContext["cart"],
102
+ appliedDiscounts: AppliedDiscount[]
103
+ ) {
104
+ return cart.map((item) => {
105
+ const itemDiscounts = appliedDiscounts.filter((discount) =>
106
+ discount.affectedItems.some((affected) => affected.productId === item.product.id)
107
+ );
108
+
109
+ const totalItemDiscount = itemDiscounts.reduce((sum, discount) => {
110
+ const affectedItem = discount.affectedItems.find(
111
+ (affected) => affected.productId === item.product.id
112
+ );
113
+ return sum + (affectedItem?.discountAmount || 0);
114
+ }, 0);
115
+
116
+ const discountPerUnit = totalItemDiscount / item.amount;
117
+ const finalPrice = item.product.price - discountPerUnit;
118
+
119
+ return {
120
+ amount: item.amount,
121
+ product: item.product,
122
+ originalPrice: Number(item.product.price.toFixed(2)),
123
+ finalPrice: Number(Math.max(0, finalPrice).toFixed(2)),
124
+ finalDiscount: Number(totalItemDiscount.toFixed(2)),
125
+ appliedDiscounts: itemDiscounts.map((d) => d.discountId),
126
+ };
127
+ });
128
+ }
129
+
130
+ static isDiscountActive(discount: TDiscount): boolean {
131
+ const now = Date.now();
132
+ return discount.active && discount.startDate <= now && discount.endDate >= now;
133
+ }
134
+
135
+ static getActiveDiscounts(discounts: TDiscount[]): TDiscount[] {
136
+ return this.filterActiveDiscounts(discounts);
137
+ }
138
+ }
@@ -34,6 +34,7 @@ export const OrderSchema = z.object({
34
34
  cartDiscount: z.number(),
35
35
  cartTotal: z.number(),
36
36
  cartVat: z.number(),
37
+ deliveryPrice: z.number().optional(),
37
38
  }),
38
39
  originalAmount: z.number().positive().optional(), // what client pay
39
40
  actualAmount: z.number().positive().optional(), // what store charge
@@ -0,0 +1,14 @@
1
+ import { z } from "zod";
2
+
3
+ // client organization for clients
4
+ export const OrganizationSchema = z.object({
5
+ id: z.string(),
6
+ name: z.string(),
7
+ discountPercentage: z.number().positive().min(0).max(100).optional(),
8
+ nameOnInvoice: z.string().optional(),
9
+ });
10
+
11
+ export const NewOrganizationSchema = OrganizationSchema.omit({ id: true });
12
+
13
+ export type TNewOrganization = z.infer<typeof NewOrganizationSchema>;
14
+ export type TOrganization = z.infer<typeof OrganizationSchema>;
@@ -23,6 +23,7 @@ export const ProfileSchema = z.object({
23
23
  createdDate: z.number(),
24
24
  lastActivityDate: z.number(),
25
25
  paymentType: ProfilePaymentTypeSchema,
26
+ organizationId: z.string().optional(),
26
27
  });
27
28
 
28
29
  export type TProfile = z.infer<typeof ProfileSchema>;