@social-mail/social-mail-web-server 1.5.330 → 1.5.331

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.
Files changed (30) hide show
  1. package/dist/server/model/entities/StoreJournal.d.ts +3 -1
  2. package/dist/server/model/entities/StoreJournal.d.ts.map +1 -1
  3. package/dist/server/model/entities/StoreJournal.js +7 -1
  4. package/dist/server/model/entities/StoreJournal.js.map +1 -1
  5. package/dist/server/model/events/StoreJournalCouponEvents.d.ts +5 -0
  6. package/dist/server/model/events/StoreJournalCouponEvents.d.ts.map +1 -1
  7. package/dist/server/model/events/StoreJournalCouponEvents.js +32 -1
  8. package/dist/server/model/events/StoreJournalCouponEvents.js.map +1 -1
  9. package/dist/server/model/events/StoreJournalEvents.d.ts.map +1 -1
  10. package/dist/server/model/events/StoreJournalEvents.js +0 -1
  11. package/dist/server/model/events/StoreJournalEvents.js.map +1 -1
  12. package/dist/server/seed/ui/seed-ui.js +1 -1
  13. package/dist/server/services/accounts/sales/SalesInvoiceService.d.ts.map +1 -1
  14. package/dist/server/services/accounts/sales/SalesInvoiceService.js +14 -6
  15. package/dist/server/services/accounts/sales/SalesInvoiceService.js.map +1 -1
  16. package/dist/server/services/coupons/CouponService.d.ts.map +1 -1
  17. package/dist/server/services/coupons/CouponService.js +8 -1
  18. package/dist/server/services/coupons/CouponService.js.map +1 -1
  19. package/dist/tsconfig.tsbuildinfo +1 -1
  20. package/dist/wwwroot/routes/store/buy/[productID]/get.d.ts.map +1 -1
  21. package/dist/wwwroot/routes/store/buy/[productID]/get.js +2 -1
  22. package/dist/wwwroot/routes/store/buy/[productID]/get.js.map +1 -1
  23. package/package.json +1 -1
  24. package/src/server/model/entities/StoreJournal.ts +10 -2
  25. package/src/server/model/events/StoreJournalCouponEvents.ts +45 -1
  26. package/src/server/model/events/StoreJournalEvents.ts +0 -2
  27. package/src/server/seed/ui/seed-ui.ts +1 -1
  28. package/src/server/services/accounts/sales/SalesInvoiceService.ts +16 -6
  29. package/src/server/services/coupons/CouponService.ts +9 -1
  30. package/src/wwwroot/routes/store/buy/[productID]/get.tsx +2 -1
@@ -1 +1 @@
1
- {"version":3,"file":"get.d.ts","sourceRoot":"","sources":["../../../../../../src/wwwroot/routes/store/buy/[productID]/get.tsx"],"names":[],"mappings":"AAGA,OAAO,IAAI,MAAM,0CAA0C,CAAC;AAE5D,OAAO,iBAAiB,MAAM,kDAAkD,CAAC;AACjF,OAAO,cAAc,MAAM,wDAAwD,CAAC;AACpF,OAAO,kBAAkB,MAAM,4DAA4D,CAAC;AAI5F,MAAM,CAAC,OAAO,MAAO,SAAQ,IAAI;IAG7B,SAAS,MAAC;IAGV,EAAE,EAAE,iBAAiB,CAAC;IAGtB,kBAAkB,EAAE,kBAAkB,CAAC;IAGvC,cAAc,EAAE,cAAc,CAAC;IAEzB,GAAG;CA4DZ"}
1
+ {"version":3,"file":"get.d.ts","sourceRoot":"","sources":["../../../../../../src/wwwroot/routes/store/buy/[productID]/get.tsx"],"names":[],"mappings":"AAGA,OAAO,IAAI,MAAM,0CAA0C,CAAC;AAE5D,OAAO,iBAAiB,MAAM,kDAAkD,CAAC;AACjF,OAAO,cAAc,MAAM,wDAAwD,CAAC;AACpF,OAAO,kBAAkB,MAAM,4DAA4D,CAAC;AAK5F,MAAM,CAAC,OAAO,MAAO,SAAQ,IAAI;IAG7B,SAAS,MAAC;IAGV,EAAE,EAAE,iBAAiB,CAAC;IAGtB,kBAAkB,EAAE,kBAAkB,CAAC;IAGvC,cAAc,EAAE,cAAc,CAAC;IAEzB,GAAG;CA4DZ"}
@@ -14,6 +14,7 @@ import { Prepare } from "@entity-access/server-pages/dist/decorators/Prepare.js"
14
14
  import SocialMailContext from "../../../../../server/model/SocialMailContext.js";
15
15
  import WebSiteService from "../../../../../server/services/files/WebSiteService.js";
16
16
  import StoreConfigService from "../../../../../server/services/store/StoreConfigService.js";
17
+ import EntityAccessError from "@entity-access/entity-access/dist/common/EntityAccessError.js";
17
18
  let default_1 = class extends Page {
18
19
  async run() {
19
20
  // only if logged in...
@@ -29,7 +30,7 @@ let default_1 = class extends Page {
29
30
  }
30
31
  const contact = await this.db.storeAccounts.where({ userID }, (p) => (x) => x.accountID === p.userID)
31
32
  .include((x) => x.addresses)
32
- .first();
33
+ .first() ?? EntityAccessError.throw(`Please signup as a store user instead of backend user.`);
33
34
  // todo: optimization
34
35
  // do not create new orders if new order for same item exists
35
36
  // with only a single item...
@@ -1 +1 @@
1
- {"version":3,"file":"get.js","sourceRoot":"","sources":["../../../../../../src/wwwroot/routes/store/buy/[productID]/get.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"get.js","sourceRoot":"","sources":["../../../../../../src/wwwroot/routes/store/buy/[productID]/get.tsx"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@social-mail/social-mail-web-server",
3
- "version": "1.5.330",
3
+ "version": "1.5.331",
4
4
  "description": "## Phase 1",
5
5
  "main": "index.js",
6
6
  "type": "module",
@@ -16,6 +16,9 @@ const journalTypeArray = [ "order", "purchase-order", "sales-invoice", "journal"
16
16
  export type journalTypeArrayType = typeof journalTypeArray[number];
17
17
 
18
18
 
19
+ const statusTypeArray = [ "new", "paid", "draft"] as const;
20
+ export type statusType = typeof statusTypeArray[number];
21
+
19
22
 
20
23
  @Table("StoreJournals")
21
24
  export class StoreJournal {
@@ -45,8 +48,13 @@ export class StoreJournal {
45
48
  @Column({ dataType: "Boolean", default: () => false })
46
49
  posted: boolean;
47
50
 
48
- @Column({ dataType: "Char", length: 50, default: () => "draft"})
49
- status: string;
51
+ @Column({
52
+ dataType: "Char",
53
+ length: 50,
54
+ default: () => "draft",
55
+ enum: statusTypeArray
56
+ })
57
+ status: statusType;
50
58
 
51
59
  @Column({ dataType: "BigInt" ,nullable: true })
52
60
  @RelateTo(StoreAccount, {
@@ -6,12 +6,18 @@ import ChangeEntry from "@entity-access/entity-access/dist/model/changes/ChangeE
6
6
  import Sql from "@entity-access/entity-access/dist/sql/Sql.js";
7
7
  import Inject from "@entity-access/entity-access/dist/di/di.js";
8
8
  import CouponService from "../../services/coupons/CouponService.js";
9
+ import SocialMailContext from "../SocialMailContext.js";
10
+ import { ForeignKeyFilter } from "@entity-access/entity-access/dist/model/events/EntityEvents.js";
11
+ import DateTime from "@entity-access/entity-access/dist/types/DateTime.js";
9
12
 
10
13
  export default class StoreJournalCouponEvents extends AuthenticatedEvents<StoreJournalCoupon> {
11
14
 
12
15
  @Inject
13
16
  couponService: CouponService;
14
17
 
18
+ @Inject
19
+ db: SocialMailContext;
20
+
15
21
  filter(query: IEntityQuery<StoreJournalCoupon>) {
16
22
  if (!this.verify) {
17
23
  return query;
@@ -38,7 +44,7 @@ export default class StoreJournalCouponEvents extends AuthenticatedEvents<StoreJ
38
44
  if (sessionUser.isAdmin) {
39
45
  return query;
40
46
  }
41
- throw new EntityAccessError("Only admin can delete the store.");
47
+ return this.modify(query);
42
48
  }
43
49
 
44
50
  includeFilter(query: IEntityQuery<StoreJournalCoupon>, type?: any, key?: string) {
@@ -47,11 +53,49 @@ export default class StoreJournalCouponEvents extends AuthenticatedEvents<StoreJ
47
53
 
48
54
  async beforeInsert(entity: StoreJournalCoupon, entry: ChangeEntry<StoreJournalCoupon>) {
49
55
  this.sessionUser.ensureLoggedIn();
56
+
57
+ if (!entity.couponID) {
58
+ await entry.loadNavigationAsync((x) => x.order);
59
+
60
+ const { storeID } = entity.order;
61
+ const { couponCode } = entity;
62
+
63
+ const ce = this.db.changeSet.getEntry(entity.order);
64
+ entity.order.dateUpdated = DateTime.now;
65
+ ce.detect();
66
+
67
+ const coupon = await this.db.storeCoupons.where({ storeID, couponCode }, (p) => (x) => x.storeID === p.storeID
68
+ && x.code === p.couponCode
69
+ )
70
+ .first() ?? EntityAccessError.throw(`Coupon ${entity.couponCode} not found`);
71
+
72
+ entity.couponID = coupon.couponID;
73
+ entity.coupon = coupon;
74
+ }
75
+
50
76
  await this.couponService.apply(entity, entry);
51
77
  }
52
78
 
79
+ async beforeDelete(entity: StoreJournalCoupon, entry: ChangeEntry<StoreJournalCoupon>) {
80
+ this.sessionUser.ensureLoggedIn();
81
+
82
+ const isNonPaid = await this.db.storeJournalCoupons.where(entity, (p) => (x) =>
83
+ x.appliedCouponID === p.appliedCouponID
84
+ && x.order.status !== "paid"
85
+ )
86
+ .first();
87
+
88
+ if (!isNonPaid) {
89
+ throw new EntityAccessError(`Coupon cannot be deleted from paid order`);
90
+ }
91
+ }
92
+
53
93
  beforeUpdate(entity: StoreJournalCoupon, entry: ChangeEntry<StoreJournalCoupon>) {
54
94
  throw new EntityAccessError(`Cannot modify coupon, delete and add it again.`);
55
95
  }
56
96
 
97
+ onForeignKeyFilter(filter: ForeignKeyFilter<StoreJournalCoupon, any>) {
98
+ return null;
99
+ }
100
+
57
101
  }
@@ -79,8 +79,6 @@ export default class StoreJournalEvents extends AuthenticatedEvents<StoreJournal
79
79
  if(entry.getChange("posted").oldValue) {
80
80
  throw new EntityAccessError("Posted journal cannot be saved as draft.");
81
81
  }
82
-
83
- await this.syncAmount(entry);
84
82
  await this.verifyEntries(entry);
85
83
 
86
84
  } else {
@@ -3,7 +3,7 @@ import semver from "semver";
3
3
 
4
4
  export default async function seedUI(config: DBConfig) {
5
5
 
6
- const version = "1.2.709";
6
+ const version = "1.2.710";
7
7
 
8
8
  const existing = await config.getValue(UIPackageConfig, false);
9
9
  if (existing) {
@@ -22,7 +22,7 @@ export default class SalesInvoiceService {
22
22
  async syncAmount(entry: ChangeEntry<StoreJournal>, entity: StoreJournal) {
23
23
 
24
24
  await this.db.storeJournals.where(entity, (p) => (x) => x.journalID === p.journalID)
25
- .include((x) => [x.lineItems.forEach((i) => [i.coupons, i.itemPrice])])
25
+ .include((x) => [x.lineItems.forEach((i) => [i.coupons.forEach((c) => c.coupon), i.itemPrice])])
26
26
  .first();
27
27
 
28
28
  for(const lineItem of [...entity.lineItems]) {
@@ -37,11 +37,15 @@ export default class SalesInvoiceService {
37
37
  const itemAmount = Number(lineItem.price) * Number(lineItem.quantity);
38
38
 
39
39
  if (lineItem.discountPercentage) {
40
- lineItem.discount = lineItem.discountPercentage * lineItem.amount;
40
+ lineItem.discount = Number(lineItem.discountPercentage) * Number(lineItem.amount);
41
+ } else {
42
+ lineItem.discount = 0;
41
43
  }
42
44
 
43
45
  const priceAfterDiscount = itemAmount - lineItem.discount;
44
46
 
47
+ lineItem.couponDiscount ??= 0;
48
+
45
49
  if (priceAfterDiscount !== Number(lineItem.priceAfterDiscount)) {
46
50
  lineItem.priceAfterDiscount = priceAfterDiscount;
47
51
  await this.db.storeJournalLineItems.statements.update(
@@ -74,7 +78,13 @@ export default class SalesInvoiceService {
74
78
 
75
79
  let taxes = 0;
76
80
 
77
- lineItem.amount = lineItem.priceAfterDiscount - lineItem.couponDiscount;
81
+ await this.coupons.compute(lineItem);
82
+
83
+ lineItem.couponDiscount = Number(lineItem.couponDiscount);
84
+ lineItem.quantity ??= 0;
85
+ lineItem.quantity = Number(lineItem.quantity);
86
+
87
+ lineItem.amount = (lineItem.priceAfterDiscount - Number(lineItem.couponDiscount)) * lineItem.quantity;
78
88
 
79
89
  for(const price of itemPrices) {
80
90
  let taxLine = lineItem.taxLineItems.find((r) =>
@@ -95,14 +105,14 @@ export default class SalesInvoiceService {
95
105
 
96
106
  if(itemPrice.taxIncluded) {
97
107
 
98
- let amount = lineItem.amount - lineItem.discount;
108
+ let amount = lineItem.amount;
99
109
  amount = amount / (Number(price.amount) + 1);
100
- lineItem.amount = amount + lineItem.discount;
110
+ lineItem.amount = amount;
101
111
 
102
112
  }
103
113
 
104
114
  taxLine.price = Number(price.amount);
105
- taxLine.total = (Number(lineItem.amount) - Number(lineItem.discount)) * Number(price.amount);
115
+ taxLine.total = Number(lineItem.amount) * Number(price.amount);
106
116
  taxes += taxLine.total;
107
117
  }
108
118
  lineItem.taxes = taxes;
@@ -39,6 +39,11 @@ export default class CouponService {
39
39
 
40
40
  let applicableItems = order.lineItems;
41
41
 
42
+ if (!orderCoupon.couponID) {
43
+ orderCoupon.couponID = coupon.couponID;
44
+ orderCoupon.coupon = coupon;
45
+ }
46
+
42
47
  if (coupon.itemID) {
43
48
  applicableItems = order.lineItems.filter((i) => i.itemID === coupon.itemID);
44
49
  if (!applicableItems.length) {
@@ -81,13 +86,16 @@ export default class CouponService {
81
86
  // set couponDiscount amount
82
87
 
83
88
  const coupons = lineItem.coupons ?? lineItem.journal.orderCoupons;
84
- if (!coupons) {
89
+ if (!coupons?.length) {
85
90
  return;
86
91
  }
87
92
 
88
93
  lineItem.couponDiscount = 0;
89
94
 
90
95
  for (const coupon of coupons) {
96
+ if (!coupon.coupon) {
97
+ await this.db.changeSet.getEntry(coupon).loadNavigationAsync((x) => x.coupon);
98
+ }
91
99
  switch(coupon.coupon.type) {
92
100
  case "discount":
93
101
  lineItem.couponDiscount += lineItem.priceAfterDiscount * Number(coupon.coupon.amount);
@@ -6,6 +6,7 @@ import { Prepare } from "@entity-access/server-pages/dist/decorators/Prepare.js"
6
6
  import SocialMailContext from "../../../../../server/model/SocialMailContext.js";
7
7
  import WebSiteService from "../../../../../server/services/files/WebSiteService.js";
8
8
  import StoreConfigService from "../../../../../server/services/store/StoreConfigService.js";
9
+ import EntityAccessError from "@entity-access/entity-access/dist/common/EntityAccessError.js";
9
10
 
10
11
 
11
12
  @Prepare.authorize
@@ -44,7 +45,7 @@ export default class extends Page {
44
45
 
45
46
  const contact = await this.db.storeAccounts.where({userID }, (p) => (x) => x.accountID === p.userID)
46
47
  .include((x) => x.addresses)
47
- .first();
48
+ .first() ?? EntityAccessError.throw(`Please signup as a store user instead of backend user.`);
48
49
 
49
50
  // todo: optimization
50
51
  // do not create new orders if new order for same item exists